При проведении документов в 1С:Предприятие пользователи могут сталкиваться с периодической ошибкой вида: «Конфликт блокировок при выполнении транзакции: Microsoft Sql Server Native Client 11.0: Превышено время ожидания запроса на блокировку. HRESULT=80040E31, SQLSTATE=HYT00, native=1222». Чаще всего эта ошибка возникает примерно в одно и то же время, заставляет пользователей ждать несколько минут, а затем сбрасывает транзакцию.
Рассмотрим подробно, почему возникает эта проблема, как провести диагностику и какие технические решения позволяют избавиться от конфликтов блокировок на стороне СУБД.
Разберем, что происходит на уровне платформы и СУБД MS SQL Server. Код ошибки native=1222 (символьный код HRESULT=80040E31) означает Lock request time out — превышение времени ожидания блокировки ресурса на уровне СУБД.
По умолчанию таймаут ожидания блокировки на уровне СУБД для платформы 1С составляет 20 секунд. Если в течение этого времени транзакция 1С не может получить доступ к строкам или таблице MS SQL, платформа прерывает операцию и выдает сообщение об ошибке.
Даже если в конфигурации 1С включен режим управляемых блокировок и используется режим изоляции транзакций Read Committed Snapshot (RCSI), операции записи (проведение документов, запись элементов справочников) всё равно запрашивают физические эксклюзивные блокировки на уровне СУБД. Если в этот же момент над таблицами базы данных выполняется монопольная операция — например, дефрагментация или перестройка индексов (ALTER INDEX REBUILD), — MS SQL накладывает блокировку схемы (Sch-M) или всей таблицы (TABLOCK). В результате любые пользовательские транзакции, обращающиеся к этим регистрам, блокируются и отваливаются по таймауту.
Проанализируем по шагам, какие инструменты помогают быстро локализовать источник проблемы:
Lock:Acquired, Lock:Escalation, а также отсчеты lock_timeout и отчеты о заблокированных процессах (blocked_process_report). Это позволяет точно определить, какой SPID (идентификатор сессии) удерживает монопольный ресурс.DBMSSQL и EXCP. Это даст возможность увидеть точные текста SQL-запросов, длительность ожидания и конкретные таблицы, к которым обращалась транзакция 1С в момент возникновения ошибки.Выяснив причину конфликта (сочетание регламентных процедур MS SQL и активной работы пользователей), выберем оптимальный способ решения.
Самое простое и надежное правило: все тяжелые регламентные процедуры СУБД (перестройка индексов, обновление статистики, сжатие) должны выполняться строго во внерабочее время (например, ночью), когда в базе данных нет активных сеансов пользователей.
Если используется редакция MS SQL Server Enterprise Edition, выполним реиндексацию с параметром ONLINE = ON. В этом режиме таблица остается доступной для чтения и записи во время перестройки индексов, а кратковременная блокировка схемы запрашивается лишь на доли секунды в самом начале и в конце операции.
Пример команды перестройки индекса:
ALTER INDEX ALL ON dbo._Document123 REBUILD WITH (ONLINE = ON);
Если используется редакция MS SQL Server Standard Edition (в которой режим ONLINE для REBUILD не поддерживается), перестройка индексов всегда наглухо блокирует таблицу. В этом случае для обслуживания в дневное время вместо REBUILD необходимо использовать команду REORGANIZE. Она работает потоково в фоновом режиме и не накладывает монопольных блокировок на таблицы.
Пример команды дефрагментации:
ALTER INDEX ALL ON dbo._Document123 REORGANIZE;
Начиная с версии MS SQL Server 2014, при выполнении онлайновой перестройки индексов можно явно указать приоритет блокировки для самого сервисного процесса. Если процесс обслуживания не может получить финальную блокировку из-за пользовательских транзакций 1С, он уступит им дорогу или завершится сам, не блокируя работу пользователей.
Пример настройки ожидания блокировки с низким приоритетом:
ALTER INDEX ALL ON dbo._Document123 REBUILD WITH
(
ONLINE = ON
(
WAIT_AT_LOW_PRIORITY
(
MAX_DURATION = 1 MINUTES,
ABORT_AFTER_WAIT = SELF
)
)
);
Проанализируем регулярность обслуживания. Не обязательно каждый день выполнять полную перестройку всех индексов базы. Достаточно настроить ежедневно легкое обновление статистики командой UPDATE STATISTICS, а глубокий REBUILD или REORGANIZE выполнять раз в неделю во время минимальной нагрузки на систему.