При миграции старых конфигураций, таких как Управление производственным предприятием (УПП) 1.3, с платформы 8.2 на 8.3 программисты часто сталкиваются с неприятным сюрпризом: система, которая годами работала стабильно, начинает генерировать взаимные блокировки (deadlocks). Ситуация кажется парадоксальной, ведь режим управляемых блокировок уже был включен, а код не менялся. Разберем подробно, почему так происходит, и какие технические нюансы платформы 8.3 вызывают эти конфликты.
Одной из главных причин появления дедлоков является изменение требований платформы к настройкам СУБД. Проанализируем механизм работы MS SQL Server в контексте 1С. Для корректной и производительной работы версии 8.3 критически важно использование режима Read Committed Snapshot Isolation (RCSI).
В чем заключается разница? Рассмотрим ситуацию:
Read Committed. В этом режиме операции чтения могли блокироваться операциями записи, и наоборот.Выясним причину, почему это ведет к дедлоку: транзакция №1 захватывает ресурс А для чтения, транзакция №2 захватывает ресурс Б для чтения. Затем №1 пытается записать в Б, а №2 — в А. Без RCSI они будут ждать друг друга вечно, пока SQL Server не принудительно завершит одну из них.
Чтобы проверить и включить этот режим, необходимо выполнить следующий скрипт в консоли SQL Management Studio:
ALTER DATABASE [Имя_Вашей_Базы] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
ALTER DATABASE [Имя_Вашей_Базы] SET READ_COMMITTED_SNAPSHOT ON;
ALTER DATABASE [Имя_Вашей_Базы] SET MULTI_USER;
Рассмотрим еще один важный аспект: почему раньше блокировок было "меньше"? На самом деле, их было больше, но они были "грубее". Платформа 8.2 зачастую накладывала блокировки на более широкие диапазоны данных или удерживала их дольше из-за менее совершенных алгоритмов планировщика.
В такой ситуации транзакции просто выстраивались в очередь. Первая транзакция блокировала "всю таблицу", а остальные ждали её завершения. В 8.3 механизмы стали более "тонкими" (гранулярными). Платформа старается блокировать только те записи, которые действительно нужны. Это повышает параллельность, но "обнажает" ошибки в последовательности захвата ресурсов в коде конфигурации.
Проанализируем классическую ситуацию дедлока в 1С:
РегистрНакопления.Продажи, затем в РегистрНакопления.ОстаткиТоваров.РегистрНакопления.ОстаткиТоваров, затем в РегистрНакопления.Продажи.В 8.2 одна из них, скорее всего, подождала бы другую целиком. В 8.3 они обе успешно выполнят первый шаг и "встретятся" на втором, вызвав дедлок. Решение здесь только одно — строгая регламентация порядка захвата ресурсов в коде.
Посмотрим на примеры из практики УПП 1.3. В старых допиленных конфигурациях часто встречаются огромные транзакции, внутри которых выполняются тяжелые запросы. Рассмотрим, как это лечится.
Ошибка: Выполнение запросов к базе данных в середине транзакции проведения, особенно если эти запросы не относятся к блокируемым данным напрямую.
Процедура ОбработкаПроведения(Отказ, Режим)
Блокировка = Новый БлокировкаДанных;
// ... установка блокировок ...
Блокировка.Заблокировать();
// ОШИБКА: Тяжелый запрос внутри транзакции
Запрос = Новый Запрос("ВЫБРАТЬ ... ИЗ РегистрНакопления.ПартииТоваровНаСкладах");
Результат = Запрос.Выполнить();
// Запись движений
Движения.Остатки.Записать();
КонецПроцедуры
Решение: Разберем по шагам правильный алгоритм. Все необходимые данные для проведения должны быть подготовлены ДО начала записи и установки управляемых блокировок. Выносите запросы за пределы захвата ресурсов, если это позволяет бизнес-логика. Если же данные должны быть актуальны именно в момент записи, используйте объект БлокировкаДанных для явного указания намерений.
Платформа 8.3 иначе работает с временными таблицами на уровне СУБД. Она чаще создает индексы автоматически и по-другому формирует структуру в tempdb. В некоторых случаях это приводит к тому, что SQL Server делает вывод об эскалации блокировок (превращение блокировки строк в блокировку всей таблицы) быстрее, чем это делала 8.2.
Если вы видите дедлоки на системных ресурсах или в tempdb, проанализируйте свои запросы на предмет использования огромных временных таблиц без явного индексирования. В 8.3 рекомендуется явно индексировать поля временных таблиц, по которым в дальнейшем будет происходить соединение.
В 8.3 архитектура кластера существенно изменилась. Появилось множество служебных фоновых процессов, которые работают более агрессивно, чем в 8.2. Например:
В старой УПП эти процессы могут пересекаться с основными транзакциями. Проверьте консоль администрирования 1С и убедитесь, что регламентные задания не запускаются слишком часто и не конфликтуют с периодами активной работы пользователей.
Подведем итог нашему анализу. Чтобы избавиться от дедлоков после перехода на 8.3, выполните следующие действия:
Остатки, затем Партии, затем Бухгалтерский).Помните, что появление дедлоков в 8.3 — это не ошибка платформы, а сигнал о том, что ваш код содержит потенциальные конфликты, которые раньше просто маскировались низкой производительностью и очередями.