При одновременной работе большого количества пользователей (например, при параллельной разноске банковских выписок и проведении платежных поручений) часто возникает проблема высокой конкуренции за ресурсы. Платформа 1С фиксирует длительные ожидания на блокировках и взаимоблокировки (Deadlock), чаще всего локализованные на регистре бухгалтерии Хозрасчетный. Разберем, как устроен механизм хранения итогов регистра бухгалтерии, почему возникают блокировки и какие меры необходимо принять для оптимизации системы.
Как устроены блокировки итогов регистра бухгалтерии
Для понимания причин конкуренции проанализируем, в какие физические таблицы СУБД платформа выполняет запись при проведении бухгалтерского документа:
Таблица движений (проводок): содержит детальные записи по дебету и кредиту с указанием точной даты, времени, счета, организации, субконто и суммы.
Таблица периодических итогов: хранит остатки и обороты с периодичностью в один календарный месяц. Периодом в данном случае является именно месяц (например, 01.03.2018), а не секунды или дни. Разница во времени между документами в пределах одного месяца (например, 22.03.2018 00:00:00 и 22.03.2018 00:00:01) относится к одной и той же строке периодических итогов. Разные счета (например, 62.01 и 62.02) формируют разные строки в таблице итогов.
Таблица текущих (оперативных) итогов: хранит актуальные остатки на точку актуальности без привязки к дате месяца. Любое проведение документа по организации и счету обновляет и эксклюзивно блокирует строку в таблице текущих итогов, даже если сами документы относятся к совершенно разным месяцам.
Таким образом, когда десятки пользователей одновременно проводят платежи по одной организации и одним и тем же счетам учета, узким горлышком становится именно таблица текущих итогов и таблица периодических итогов за текущий месяц.
Шаг 1. Проверка и настройка регламентов обслуживания базы данных
Прежде чем переходить к доработке конфигурации, выполним диагностику и регламентное обслуживание итогов:
Актуальность рассчитанных итогов: Проверим период рассчитанных итогов регистра бухгалтерии. Если итоги не рассчитаны или рассчитаны на дату далеко в прошлом, платформа при каждом обращении к остаткам вынуждена вычислять данные «на лету» по таблице движений, удерживая долгие блокировки.
Поиск некорректных дат документов: Проанализируем регистр на наличие записей с аномальными периодами (например, документов, ошибочно введенных 2108 или 2001 годом). Подобные записи искусственно растягивают диапазон таблицы итогов и приводят к деградации производительности СУБД.
Установка минимального периода хранения итогов: Для давно работающих информационных баз рекомендуется настроить минимальный период хранения итогов, чтобы платформа не рассчитывала пустые периоды за прошлые годы.
Регламентные процедуры СУБД: Убедимся, что на сервере баз данных регулярно выполняются дефрагментация/реиндексация таблиц и обновление статистик.
Шаг 2. Использование механизма разделения итогов
Для устранения конкуренции за одни и те же строки в таблице итогов включим механизм разделения итогов. В этом режиме платформа записывает изменения не в одну общую строку, а распределяет их по нескольким записям со случайным номером разделителя.
Включается режим в свойствах регистра бухгалтерии в конфигураторе или программно:
// Включение разделения итогов для регистра бухгалтерии
РегистрыБухгалтерии.Хозрасчетный.УстановитьИспользованиеРазделителяИтогов(Истина);
Важно: При включенном разделении итогов обязательно должно быть настроено и регулярно выполняться регламентное задание Слияние разделенных итогов, чтобы предотвратить избыточное разрастание таблиц СУБД.
Шаг 3. Отключение использования текущих итогов
Если в процессе оперативной работы пользователей и проведения платежных документов не требуется ежесекундный расчет актуальных остатков по счетам в реальном времени, отключим использование текущих итогов для регистра бухгалтерии:
// Отключение оперативных итогов снижает нагрузку на СУБД
РегистрыБухгалтерии.Хозрасчетный.УстановитьИспользованиеТекущихИтогов(Ложь);
После отключения текущих итогов платформа перестает обновлять и блокировать отдельную таблицу оперативных итогов при каждой проводке, выполняя запись только в таблицу периодических итогов соответствующего месяца.
Шаг 4. Оптимизация транзакций и перевод на управляемые блокировки
Разберем способы сокращения времени удержания блокировок в коде проведения:
Перевод конфигурации на управляемый режим блокировок: При использовании СУБД MS SQL Server переведем базу в режим версионирования строк (включаем параметры READ_COMMITTED_SNAPSHOT ON и ALLOW_SNAPSHOT_ISOLATION ON). Это исключит взаимные блокировки между операциями чтения данных и записью проводок.
Сокращение тела транзакции: Вынесем все длительные операции (проверки заполнения, формирование отчетов, обращение к внешним сервисам) за пределы транзакции проведения.
Запись набора в самом конце: Установим свойство набора записей Записывать = Истина непосредственно перед завершением процедуры обработки проведения, чтобы минимизировать время жизни эксклюзивной блокировки.
Шаг 5. Альтернативные варианты архитектуры (отложенное проведение)
Если поток документов крайне велик и оптимизация не дает достаточного запаса производительности, рассмотрим разделение оперативного и бухгалтерского учета:
Асинхронная проводка по БУ: При проведении платежного документа формируются только движения по оперативным регистрам (взаиморасчеты, банк).
Формирование проводок регламентным заданием: Запись проводок по регистру бухгалтерии выполняется в фоновом режиме пачками документов или переносится на ночное время. При пакетировании записи проводки упорядочиваются по счетам и периодам, что исключает взаимные блокировки между фоновыми потоками.