Почему возникают блокировки при проведении документов и как их устранить?

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

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

Выясним причину: почему возникает блокировка?

Проанализируем механизм работы 1С в автоматическом режиме. При использовании этого режима платформа устанавливает уровень изоляции транзакций SERIALIZABLE на стороне SQL Server. Это самый жесткий уровень изоляции, необходимый для обеспечения полной целостности данных. Его главная особенность — использование блокировок диапазонов (Range Locks).

Рассмотрим, как это работает на практике. Когда первый сеанс начинает проведение документа (например, Чек ККМ), он накладывает блокировки на записи в регистрах. В режиме SERIALIZABLE SQL Server блокирует не только конкретную строку с товаром, но и весь диапазон значений индекса вокруг этой строки. Если второй сеанс пытается продать тот же товар или даже другой товар, который попадает в «заблокированный диапазон», транзакция второго сеанса приостанавливается и ожидает завершения первой.

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

Эскалация блокировок и неоптимальные индексы

Проанализируем еще одну причину — эскалацию блокировок. Если транзакция изменяет большое количество строк (обычно более 5000 в одной таблице), SQL Server может решить, что управлять множеством мелких блокировок слишком накладно. В этом случае он заменяет их одной исключительной блокировкой всей таблицы (Table Lock). В этот момент работа всех остальных пользователей с данной таблицей полностью прекращается.

Также важно обратить внимание на индексы. Если запрос внутри транзакции (например, по регистру ЦеныАТТ) не может эффективно использовать существующие индексы, SQL Server вынужден выполнять сканирование всей таблицы (Table Scan). В режиме SERIALIZABLE это автоматически приводит к блокировке всей таблицы до момента фиксации транзакции.

Решение 1: Переход на управляемый режим блокировок

Это стратегически верный и наиболее эффективный способ решения проблемы. Разберем по шагам, что дает переход на управляемые блокировки:

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

Для реализации этого метода необходимо в свойствах конфигурации (или конкретных объектов) установить режим управления блокировками в значение Управляемый и в коде процедуры ОбработкаПроведения явно прописать установку блокировок:


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

Решение 2: Включение режима READ_COMMITTED_SNAPSHOT (RCSI)

Если переход на управляемые блокировки требует слишком больших трудозатрат, можно попробовать оптимизировать работу СУБД. Включение механизма Snapshot Isolation на уровне MS SQL Server позволяет читающим запросам получать данные из версии строк в tempdb, не ожидая завершения транзакций записи.

Однако помните: в автоматическом режиме 1С все равно будет форсировать уровень SERIALIZABLE для многих операций записи, поэтому эффект от RCSI может быть ограниченным. Этот метод лучше всего работает в паре с переходом на управляемый режим.

Решение 3: Оптимизация регистров и разделение итогов

Рассмотрим дополнительные методы повышения параллельности:

Как диагностировать проблему самостоятельно?

Если вы столкнулись с «зависанием», воспользуйтесь следующей методикой:

  1. Определите SPID (идентификатор процесса) заблокированного сеанса в 1С.
  2. В SQL Server Management Studio выполните команду sp_who2, чтобы увидеть, какой процесс блокирует ваш SPID.
  3. Используйте команду DBCC INPUTBUFFER(НомерПроцесса), чтобы увидеть последний запрос, вызвавший проблему.
  4. Проанализируйте план выполнения этого запроса. Если вы видите Index Spool или Table Scan при уровне изоляции SERIALIZABLE — это явный признак необходимости оптимизации индексов или перехода на управляемый режим.

Посмотрим на пример типичного запроса, который может вызвать блокировку в автоматическом режиме (из-за отсутствия NOLOCK в транзакции):


SELECT TOP 21 
    _Document236_R._Date_Time AS _A1, 
    _Document236_R._Number AS _A2, 
    _Document236_R._IDRRef AS _A11RRef 
FROM _Document236 _Document236_R WITH(SERIALIZABLE) 
WHERE _Document236_R._Date_Time = @P2
ORDER BY _Document236_R._Date_Time

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

← На главную