Почему запрос к виртуальной таблице остатков блокирует проведение документов и как это исправить

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Управленческий учет IT и автоматизация бизнеса
← На главную

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

Причины блокировки таблиц при выполнении запросов на чтение

Проанализируем техническую сторону взаимодействия платформы 1С и СУБД. Поведение блокировок зависит от установленного режима управления блокировками данных и структуры самих запросов:

  1. Автоматический режим блокировок и уровень изоляции транзакций. Если для конфигурации или конкретного регистра накопления установлен автоматический режим управления блокировками, СУБД использует уровни изоляции REPEATABLE READ или SERIALIZABLE. При чтении данных внутри транзакции накладываются разделяемые блокировки (S-блокировки). Они удерживаются до самого окончания транзакции. В это же время проведение документов требует установки монопольных блокировок (X-блокировок) на те же диапазоны данных, что приводит к взаимным блокировкам и таймаутам.
  2. Смешанный режим блокировок. Если в свойствах конфигурации включен управляемый режим, но у самого регистра накопления свойство Режим управления блокировкой данных оставлено в значении Автоматический, то любые операции с этим регистром продолжают выполняться по правилам автоматических блокировок на уровне СУБД.
  3. Эскалация блокировок (Lock Escalation). Если запрос регламентного задания считывает огромный массив записей за один раз, СУБД для экономии системных ресурсов объединяет множество мелких построчных блокировок в одну общую блокировку всей таблицы (эскалация блокировки). В этот момент проведение любых документов по данному регистру становится невозможным.
  4. Специфика работы виртуальных таблиц остатков. Виртуальная таблица Остатки физически обращается к таблице итогов и таблице движений регистра (для досчета движений от точки рассчитанных итогов до переданного момента времени). Если граница итогов не сдвинута на актуальную дату, запрос сканирует широкий диапазон записей в таблице движений, удерживая разделяемые блокировки на всех затронутых строках.

Способ 1. Оптимизация регламентного задания и запросов на чтение

Рассмотрим первоочередные меры, которые позволяют снизить нагрузку и исключить блокировку таблиц без кардинальной переработки конфигурации:

  1. Исключение неявных транзакций при чтении. Проверим код регламентного задания: запрос на выборку остатков не должен быть обернут в транзакцию (НачатьТранзакцию() ... ЗафиксироватьТранзакцию()). Чтение вне транзакции позволяет СУБД снимать блокировки чтения сразу в момент завершения выборки строк, а не удерживать их до завершения всего фонового процесса.
  2. Фильтрация в параметрах виртуальной таблицы. Передадим все условия отбора (по складам, номенклатуре, организациям) непосредственно в параметры виртуальной таблицы, а не в секцию ГДЕ. Это позволит СУБД использовать кластерные индексы таблицы итогов и не сканировать лишние строки.
  3. Порционная обработка данных. Если регламентному заданию требуется обработать всю номенклатуру базы, разобьем выборку на небольшие пакеты данных, чтобы предотвратить эскалацию блокировок на уровне СУБД до блокировки всей таблицы.

Способ 2. Актуализация итогов регистров накопления

Если виртуальная таблица остатков обращается к неактуальным итогам, СУБД вынуждена накладывать блокировки на таблицу движений. Настроим регламентный пересчет итогов:

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

Способ 3. Перевод регистра и документов в управляемый режим блокировок

Наиболее эффективным решением проблемы параллельности чтения и записи является использование управляемого режима блокировок платформы 1С:

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

Посмотрим на пример установки управляемой блокировки в модуле проведения документа:


Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.ТоварыНаСкладах");
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
ЭлементБлокировки.УстановитьЗначение("Склад", Склад);
ЭлементБлокировки.ИсточникДанных = ТаблицаТоваров;
ЭлементБлокировки.ИспользоватьИзИсточникаДанных("Номенклатура", "Номенклатура");
Блокировка.Заблокировать();

Таким образом, сочетание оптимизации запросов, регулярного смещения границы рассчитанных итогов и перехода на управляемый режим позволяет полностью исключить взаимоблокировки регламентных заданий и проводящихся документов.

← На главную