Почему скачут остатки в Оборотно-сальдовой ведомости 1С и как решить проблему тормозов на больших базах

Системный администратор 1С v8.3 (Обычные формы) Бухгалтерский учет
← На главную

Работа с крупными информационными базами «1С:Предприятие» (объемом около 1 Тб и более) накладывает особую ответственность на администраторов СУБД и разработчиков. В процессе эксплуатации таких систем можно столкнуться с крайне загадочным симптомом: при одновременной работе множества пользователей регламентированные отчеты (например, Оборотно-сальдовая ведомость) начинают выдавать разные, постоянно «скачущие» цифры при каждом перезапуске. При этом база данных работает медленно, а сервер СУБД испытывает серьезные нагрузки.

В этой статье мы подробно разберем физику этого процесса, выясним причины сбоев и предложим проверенные практические решения для нормализации работы системы.

---

Физика процесса: почему «скачут» остатки при грязном чтении (NOLOCK)

Для того чтобы понять, почему один и тот же отчет, запущенный с разницей в несколько секунд, выдает разные результаты, нам необходимо обратиться к механизмам работы СУБД MS SQL Server с блокировками. По умолчанию в платформе «1С:Предприятие» большинство запросов на получение данных для отчетов выполняются в режиме так называемого «грязного чтения» (грязное чтение реализуется через хинт NOLOCK или уровень изолированности транзакций READ UNCOMMITTED). Это сделано для того, чтобы тяжелые аналитические отсчеты не блокировали запись новых документов оперативными пользователями.

Однако при высокой интенсивности записи транзакций режим NOLOCK может приводить к двум неприятным физическим явлениям на уровне дисковых страниц СУБД:

  1. Чтение незафиксированных данных (Dirty Reads): В процессе проведения крупного документа система записывает промежуточные движения в таблицы базы данных. Если в эту же миллисекунду пользователь формирует ОСВ, запрос считывает эти временные, еще не подтвержденные (незакоммиченные) данные. Если транзакция проведения документа в итоге откатится (например, из-за нехватки остатков или ошибки в коде), отчет все равно покажет эти «фантомные» цифры. При повторном формировании отчета этих данных уже не будет.
  2. Эффект смещения страниц (Page Splits / Data Movement): Это основная причина «скачущих» цифр на быстродействующих серверах. Данные в SQL Server хранятся на страницах объемом 8 Кб, организованных в виде B-дерева. Когда параллельный процесс записывает новые строки в таблицу, свободное место на странице заканчивается, и SQL Server выполняет расщепление страницы (Page Split), перенося часть строк на новую физическую страницу. Если сканирующий запрос отчета в режиме NOLOCK проходит по страницам в момент их расщепления, он может прочитать одну и ту же строку дважды (если она переместилась вперед по ходу сканирования) или полностью пропустить ее (если она переместилась назад). Физически в базе данные корректны, но отчет возвращает ложный, «скачущий» результат.

Для решения этой проблемы на уровне СУБД применяется перевод базы данных в режим RCSI (Read Committed Snapshot Isolation). В этом режиме читающие запросы всегда видят согласованную версию данных на момент начала запроса, считывая их из версионного хранилища в системной базе tempdb, не накладывая блокировок и не страдая от «грязного» чтения.

Включить данный режим в MS SQL Server можно следующим скриптом:


ALTER DATABASE [ИмяВашейБазы] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
ALTER DATABASE [ИмяВашейБазы] SET READ_COMMITTED_SNAPSHOT ON;
ALTER DATABASE [ИмяВашейБазы] SET MULTI_USER;

---

Временные движения и загадочная пустая дата (01.01.0001)

Иногда администраторы замечают, что при формировании отчетов проскальзывают записи с пустой датой (01.01.0001). Давайте разберем, откуда они берутся.

При записи наборов записей регистров платформа 1С использует оптимизированные алгоритмы. Во время транзакции записи движений платформа может сначала очистить существующие движения (записав пустой набор) или временно проинициализировать структуру таблицы со значениями по умолчанию. На физическом уровне СУБД эти строки на короткое время могут получить значения пустой даты.

Если в этот микросекундный интервал времени выполняется тяжелый запрос отчета в режиме NOLOCK, он успевает прочитать эти промежуточные «технические» записи с пустой датой. В результате в ОСВ ломаются входящие остатки, так как движения на пустую дату влияют на расчет итогов по всему периоду. После завершения транзакции СУБД фиксирует корректные даты движений, и при следующем формировании отчета аномалия исчезает.

---

Главный виновник: сбой итогов регистров и методы его лечения

Наиболее частой причиной стабильно неверных данных и колоссальных тормозов при формировании ОСВ является рассинхронизация или отключение итогов регистров за старые периоды.

В системе 1С данные хранятся в двух связанных таблицах: таблице движений (индивидуальные записи документов) и таблице итогов (сгруппированные агрегаты по месяцам). При формировании отчета на определенную дату система не рассчитывает баланс с самого начала ведения учета. Она берет ближайшую рассчитанную точку из таблицы итогов и прибавляет/вычитает к ней движения только за короткий промежуток времени между датой отчета и точкой итогов.

Если итоги за прошлые периоды (например, за 2015-2016 годы) по какой-то причине повреждены или не рассчитаны, происходят следующие критические сбои:

Важно понимать: обычный пересчет итогов за последние несколько месяцев (который часто делают администраторы для экономии времени) не решает проблему, если сбой произошел в более ранних периодах. Необходимо выполнить полный пересчет итогов с самого начала ведения учета.

На терабайтной базе данных стандартный пересчет через режим «Тестирование и исправление» (ТиИ) в монопольном режиме может занять несколько суток, что недопустимо для работающего бизнеса. В такой ситуации мы рекомендуем использовать штатную обработку «Управление итогами» в режиме Предприятия:

  1. Перейдите в раздел управления итогами в вашей конфигурации.
  2. Установите границу рассчитанных итогов на самый ранний период (например, на дату начала ведения учета).
  3. Запустите пошаговый пересчет итогов, постепенно сдвигая границу вперед к текущему месяцу. Этот процесс выполняется платформой порционно, более щадящим образом для СУБД, и его можно выполнять в периоды минимальной активности пользователей без полной остановки системы.

Для автоматизации этого процесса в нерабочее время можно использовать программный пересчет с помощью встроенного языка 1С:


ГраницаИтогов = '20120101000000'; // Пример начальной даты
РегистрыБухгалтерии.Хозрасчетный.УстановитьПериодРассчитанныхИтогов(ГраницаИтогов);
РегистрыБухгалтерии.Хозрасчетный.ПересчитатьИтоги();

---

Оптимизация регламентного обслуживания MS SQL Server для баз 1 Тб+

Для стабильной работы крупных баз данных стандартные планы обслуживания MS SQL Server («Планы обслуживания» из графического интерфейса SSMS) не подходят, так как они запускают тяжелые операции без оглядки на текущую нагрузку и размер таблиц.

Давайте рассмотрим комплекс правил «осторожного» обслуживания крупных баз:

  1. Интеллектуальная дефрагментация индексов. Не используйте тотальный REBUILD для всех таблиц подряд. Используйте скрипты (например, популярное решение от Ola Hallengren), которые оценивают процент фрагментации каждого индекса индивидуально:
    • Фрагментация менее 5% — индекс не трогаем.
    • Фрагментация от 5% до 30% — выполняем легкую реорганизацию (REORGANIZE), которая не блокирует таблицу и работает в разы быстрее.
    • Фрагментация более 30% — выполняем перестроение индекса (REBUILD), по возможности с опцией ONLINE = ON (доступно в Enterprise-версиях MS SQL).
  2. Умное обновление статистики. База данных 1С крайне чувствительна к актуальности статистики. Если статистика устарела, оптимизатор SQL строит неверный план запроса (например, выбирает полное сканирование таблицы вместо поиска по индексу). На терабайтных базах обновление статистики с параметром FULLSCAN по всей базе может «повесить» сервер.

    Рекомендуется обновлять статистику выборочно — только для тех таблиц, в которых за сутки изменилось более 10% строк. Для гигантских таблиц движений (таблицы с префиксами _AccumReg и _InfoReg) используйте обновление с ограниченной выборкой (например, WITH SAMPLE 20 PERCENT).

  3. Асинхронное фоновое обновление статистики. Обязательно включите в свойствах базы данных опцию AUTO_UPDATE_STATISTICS_ASYNC (Асинхронное автоматическое обновление статистики). Это позволит избежать ситуации, когда запрос пользователя внезапно «зависает» на несколько минут из-за того, что СУБД решила прямо во время выполнения его запроса пересчитать устаревшую статистику по таблице. При включенной опции запрос выполнится по старому плану, а обновление запустится в фоновом режиме.

---

Риски при включении RCSI для баз объемом 1 Тб

Переход на механизм READ_COMMITTED_SNAPSHOT (RCSI) является стандартом для крупных систем 1С, однако он несет в себе скрытые риски, о которых системный администратор должен знать заранее.

При включении RCSI все изменяемые версии строк транслируются в базу данных TempDB. Для базы объемом 1 Тб с интенсивным вводом документов это означает колоссальный рост нагрузки на дисковую систему, где расположена TempDB. Если подсистема хранения TempDB медленная, вы получите жесткие просадки по производительности всей СУБД.

Для предотвращения этой проблемы выполните оптимизацию TempDB по шагам:

  1. Разместите файлы TempDB исключительно на самых быстрых SSD/NVMe дисках в системе.
  2. Разбейте TempDB на несколько файлов данных равного размера. Количество файлов должно соответствовать количеству физических ядер процессора (но не более 8 файлов, если у вас многоядерный сокет, дальнейшее увеличение редко дает прирост).
  3. Установите одинаковый фиксированный шаг авторасширения для всех файлов TempDB, чтобы избежать их неравномерного заполнения.

---

Баги компоновщика данных (СКД) в платформе

Иногда «скачущие» остатки в сложных аналитических отчетах вызваны не проблемами с СУБД, а внутренними ошибками самой платформы «1С:Предприятие». В некоторых релизах ветки 8.3 (в частности, до релиза 8.3.11) присутствовал баг в механизме оптимизации запросов Системы компоновки данных (СКД).

При использовании вертикальных группировок по периодам в отчетах, построенных на виртуальных таблицах остатков и оборотов, компоновщик неверно транслировал роли полей остатков в итоговый T-SQL запрос. Это приводило к некорректному соединению таблиц на уровне СУБД и так называемому «размножению остатков» (цифры удваивались или утраивались случайным образом).

Как диагностировать эту проблему: попробуйте временно добавить в группировку отчета поле детальных записей (например, регистратор/документ движения). Если после этого остатки перестали «плясать» и выстроились в корректную цепочку — вы столкнулись именно с багом компоновщика. Решением в данном случае является только обновление технологической платформы «1С:Предприятие» до актуального стабильного релиза.

---

Итоги и чек-лист для администратора

Давайте резюмируем последовательность шагов, которые мы должны предпринять при обнаружении плавающих цифр в отчетах и тормозов на крупной базе 1С:

  1. Проверить актуальность рассчитанных итогов по всем регистрам накопления и бухгалтерии начиная с самых ранних периодов (2012-2015 гг.). При необходимости выполнить полный пересчет итогов с помощью обработки «Управление итогами».
  2. Перевести базу данных MS SQL в режим работы READ_COMMITTED_SNAPSHOT (RCSI), предварительно оптимизировав дисковую подсистему и структуру файлов базы данных TempDB.
  3. Настроить интеллектуальные планы обслуживания СУБД с использованием адаптивной дефрагментации индексов и секционного обновления статистики по порогу изменений строк.
  4. Убедиться, что технологическая платформа 1С обновлена до стабильного релиза, не содержащего известных багов оптимизатора СКД.
← На главную