Проблемы с производительностью в крупных торговых сетях часто проявляются внезапно: система, которая работала стабильно месяцами, начинает выдавать ошибки о превышении времени ожидания или, что еще хуже, сообщения о взаимоблокировках (deadlocks). Разберем по шагам, как диагностировать эти конфликты и какие меры необходимо предпринять на уровне СУБД и программного кода 1С.
Для начала проанализируем саму суть проблемы. Ожидание блокировки — это ситуация, когда Транзакция №1 захватила ресурс, а Транзакция №2 ждет его освобождения. Если первая транзакция выполняется слишком долго, у второй истекает время ожидания (TTIMEOUT).
Взаимоблокировка (Deadlock) — это «мертвый узел». Процесс А блокирует Таблицу 1 и пытается достучаться до Таблицы 2. В это же время Процесс Б уже заблокировал Таблицу 2 и ждет доступа к Таблице 1. Они никогда не освободят ресурсы сами. В этом случае SQL Server выбирает «жертву» (deadlock victim) и принудительно прерывает одну из транзакций, чтобы дать возможность работать другой. Именно это часто наблюдается в модулях партионного учета.
Если проблема возникла прямо сейчас, рассмотрим инструменты оперативного реагирования:
Session ID, который является инициатором блокировки, и увидеть текст конкретного SQL-запроса.start time) более 3–5 минут назад, это повод для беспокойства. Для принудительного завершения зависшего процесса используем KILL [ID процесса].Выясним причину, почему SQL Server может выбирать неоптимальные планы запросов, что приводит к избыточным блокировкам. Одной из главных причин является неактуальная статистика. Проанализируем настройки обслуживания:
Обновление статистики: SQL-сервер строит план выполнения запроса на основе данных о распределении значений в таблицах. Если статистика устарела, сервер может вместо поиска по индексу (Index Seek) выбрать полное сканирование таблицы (Index Scan), блокируя при этом тысячи лишних строк.
Очистка процедурного кэша: Иногда в кэше застревает «плохой» план запроса. Чтобы заставить сервер пересчитать планы, используем команду:
DBCC FREEPROCCACHE;
Важно помнить, что эти действия — лишь временная мера. Если код написан неоптимально, дедлоки вернутся.
Проанализируем критически важные настройки СУБД, которые часто игнорируются:
READ_COMMITTED_SNAPSHOT. Это позволит читающим запросам не блокироваться пишущими, что кардинально снижает количество конфликтов.Рассмотрим ситуацию с точки зрения разработки. Взаимоблокировки почти всегда возникают из-за разного порядка обращения к таблицам в разных частях кода. Разберем пример:
РегистрНакопления.ТоварыНаСкладах, затем РегистрНакопления.ПартииТоваров.РегистрНакопления.ПартииТоваров, затем пытается изменить РегистрНакопления.ТоварыНаСкладах.Чтобы этого избежать, необходимо соблюдать единый порядок захвата ресурсов во всей конфигурации. В типовых решениях 1С принят алфавитный порядок или порядок, определенный методологией фирмы 1С.
Проанализируем использование управляемых блокировок. Если в конфигурации установлен режим «Управляемый», мы обязаны явно прописывать блокировки перед чтением данных для последующего изменения. Посмотрим на пример правильного использования объекта БлокировкаДанных:
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.ПартииТоваров");
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
ЭлементБлокировки.УстановитьЗначение("Организация", ВыбОрганизация);
Блокировка.Заблокировать();
Если в модуле партионного учета (например, УправлениеЗапасамиПартионныйУчет) отсутствуют такие конструкции при включенных управляемых блокировках, это неизбежно приведет к хаосу в транзакциях SQL.
Если вышеописанные методы не помогли, настроим Технологический Журнал (ТЖ) для сбора событий TDEADLOCK. Это единственный надежный способ увидеть полную картину на стороне сервера 1С. В файле logcfg.xml добавим сбор событий:
<event query="true">
<eq property="Name" value="TDEADLOCK"/>
</event>
<event query="true">
<eq property="Name" value="TTIMEOUT"/>
</event>
Проанализировав логи ТЖ, мы получим точные метаданные объектов 1С и строки кода, которые участвовали в конфликте. Это позволит точечно исправить алгоритмы проведения документов.
MAXDOP=1 и включить RCSI для режима управляемых блокировок.БлокировкаДанных перед записью в регистры.Выполнение этих шагов позволит минимизировать конфликты даже в условиях высокой нагрузки торговой сети.