Заказать консультацию специалиста 1С

ИнфоСофт использует файлы «cookie» с целью персонализации сервисов и повышения удобства пользования веб-сайтом. Вы можете запретить обработку сookies в настройках браузера. Пожалуйста, ознакомьтесь с политикой использования cookies.
Оставаясь на сайте, вы соглашаетесь с политикой использования cookies.

Прорыв блокировок на MS SQL через Управляемые

Дорошкевич Антон Посмотреть все статьи >> Руководитель специализированных проектов партнерской сети «ИнфоСофт».
20.07.2026
292
Время прочтения - 7 мин.
Заказать консультацию

Недавно с командой разбирали очень странную проблему. MS SQL решил поиграть в автоматические блокировки внутри Управляемого режима. Когда решение найдено, то ларчик открывается легко. Но в моменте, скажу честно, сначала растерялись.

В статье описал наш ход мыслей и, конечно, причину блокировки.

Кого похожая проблема застала врасплох: скачайте полезный материал по кнопке ниже, чтобы быстрее во всём разобраться.

Скачайте инструкцию по выполнению
регламентных операций на уровне СУБД

Когда поняли, что что-то идёт не так

На MS SQL было огромное количество таймаутов. Конфигурация работала на управляемых блокировках, а значит, по всем законам жанра любые ожидания должны фиксироваться на уровне 1С с событием TTIMEOUT, а не EXCP.

Пользователи сотни раз в час получали такое сообщение:

Конфликт блокировок при выполнении транзакции Microsoft SQL Server Native Client: Превышено время ожидания запроса на блокировку.

При этом виновниками блокировок судя по анализу таймаутов были совершенно безобидные запросы select. Впрочем, не только они. Руки приложили и update, и insert, и delete на самых разных таблицах. В этом нет никакой системности, ни одного подозреваемого, а ещё совершенно непонятно поведение СУБД. Выглядело так, будто мы работаем на автоматических, а не на управляемых блокировках…

В поисках проблемы

Долго ломали голову, с какой стороны подойти к анализу. О решении думать было ещё рано. По ощущениям в системе был не просто баг, а «ушиб всей бабки».

Первым делом пошли смотреть на железо самой СУБД. Сделали запрос:

SELECT DB_NAME(tl.resource_database_id) AS database_name, tl.request_session_id, tl.request_mode AS lock_type,* FROM sys.dm_tran_locks tl WHERE DB_NAME(tl.resource_database_id) = 'erp' ORDER BY tl.request_session_id

Запрос показывал очень странный вывод: в колонке resource_type была только запись OBJECT. Это означает, что виновник блокировки лочит всю таблицу, а не конкретную запись/записи в ней.

Если бы блокировались записи (как оно и должно быть на управляемом режиме), то в колонке resource_type должна была быть запись KEY.

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

Но мы-то с вами точно знаем, что чудес не бывает! Поэтому берёмся за работу. На соседней базе, на этом же сервере СУБД, выполняем запрос, который начинает транзакцию на чтение. Внутри 1С становится на паузу в минуту, а мы успеваем посмотреть, что и как она блокирует.

BEGIN TRANSACTION; 
SELECT * FROM dbo._InfoRg178 T1 WITH (HOLDLOCK) WHERE T1._Fld80 = 'test'
WAITFOR DELAY '00:01:00';
COMMIT TRANSACTION;

И видим, что СУБД совершенно корректно блокирует по KEY, то есть конкретную запись в таблице.Такой же запрос в проблемной базе, блокирует всю таблицу — OBJECT.

Значит, разница именно в какой-то настройке в базе, а не в сервере СУБД!

Всем, кому актуальна тема эксплуатации КОРП-платформы на PostgreSQL, рекомендую посмотреть запись бесплатного вебинара. Там рассказываю, зачем, кому и когда нужна эта связка.

Смотреть вебинар

Как всё решилось?

В итоге решение нашлось. Начиная с версии платформы 8.3.22 необходимо выполнять дефрагментацию индексов по следующему алгоритму:

01До дефрагментации включить страничные блокировки
Пример команды: ALTER INDEX index_name ON table_name SET (ALLOW_PAGE_LOCKS = ON, ALLOW_ROW_LOCKS = ON);
02Выполнить саму дефрагментацию
03Обратно включить страничные блокировки
Пример команды: ALTER INDEX index_name ON table_name SET (ALLOW_PAGE_LOCKS = OFF, ALLOW_ROW_LOCKS = ON);

На последнем шаге в плане обслуживания проблемной базы нужно установить ALLOW_ROW_LOCKS = OFF. Это отключит у MS SQL возможность использовать индексы, и SQL Server будет вынужден применять только табличные блокировки.

Причина проблемы скрывалась именно в установленном параметре ALLOW_ROW_LOCKS = OFF для всех индексов всех таблиц базы.

Проверить наличие такой настройки в индексах базы можно запросом:

select object_id, name, allow_row_locks from sys.indexes where allow_row_locks = 0

Важно

Нужно читать очень внимательно документацию, там всё написано верно, но так, что может и ввести в заблуждение. А ещё рекомендую проверить свои планы обслуживания баз на MS SQL.


Заказать консультацию специалиста 1С

Оставьте заявку и наши эксперты проконсультируют вас по данной статье
Рассказать друзьям
Для разработчиков 1С
Вам может быть интересно: