Перевод конфигурации "Управление торговлей 10.3" (УТ 10.3) на управляемые блокировки — это одна из наиболее эффективных мер по повышению производительности системы при большом количестве одновременно работающих пользователей. В автоматическом режиме блокировок платформа 1С использует возможности СУБД для обеспечения целостности данных, что часто приводит к избыточным блокировкам таблиц и возникновению Deadlocks (взаимоблокировок). Переход на управляемый режим позволяет нам самим определять, какие данные и в какой момент должны быть заблокированы.
Рассмотрим подробнее этот процесс, разберем по шагам необходимые изменения в конфигурации, настройках сервера и программном коде.
Прежде всего, нам необходимо изменить режим управления блокировкой данных в самой информационной базе. Откроем конфигуратор и проанализируем свойства корневого узла конфигурации. Установим параметр Режим управления блокировкой данных в значение Управляемый.
Важно понимать, что после этого изменения все объекты (регистры, справочники) по умолчанию также перейдут в управляемый режим. Однако мы рекомендуем проверить наиболее нагруженные регистры накопления (такие как ТоварыНаСкладах, ПартииТоваровНаСкладах, Продажи) и убедиться, что в их свойствах также стоит режим Управляемый.
Разберем также вопрос о режиме разделения итогов. Для высоконагруженных регистров накопления, где происходит интенсивная запись (например, регистр Продажи), включение режима Разделения итогов позволит нескольким пользователям записывать данные одновременно без ожидания друг друга. Однако для регистров остатков, где важен строгий контроль отрицательных значений, этот механизм стоит использовать с осторожностью.
Когда мы переводим 1С в управляемый режим, уровень изоляции транзакций на SQL-сервере меняется с Repeatable Read на Read Committed. Это означает, что читающие транзакции больше не блокируют записывающие. Чтобы это работало максимально эффективно, проанализируем состояние базы данных на SQL-сервере.
Нам необходимо включить механизм Read Committed Snapshot Isolation (RCSI). Это позволит платформе считывать последнюю зафиксированную версию данных из tempdb, не ожидая завершения транзакций записи. Без этой настройки вы можете не почувствовать значительного прироста производительности.
Это самый трудоемкий этап. УТ 10.3 построена на так называемой "старой" методике проведения: сначала система считывает остатки из регистров, проверяет их наличие, а затем записывает новые движения. В управляемом режиме чтение данных запросом не блокирует эти данные для других пользователей. Если два пользователя одновременно считают остатки одного и того же товара, они оба увидят, что товар есть в наличии, и оба проведут документ, что приведет к отрицательным остаткам.
Чтобы этого избежать, мы должны явно устанавливать блокировку перед выполнением запроса на получение остатков. Рассмотрим пример установки блокировки в процедуре ОбработкаПроведения документа РеализацияТоваровУслуг:
// Создаем объект блокировки данных
Блокировка = Новый БлокировкаДанных;
// Добавляем элемент блокировки для регистра ТоварыНаСкладах
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.ТоварыНаСкладах");
// Устанавливаем режим: Исключительный (запрещает и чтение, и запись другим)
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
// Важно минимизировать пространство блокировки
// Передаем таблицу товаров документа в качестве источника данных
ЭлементБлокировки.ИсточникДанных = Товары;
ЭлементБлокировки.ИспользоватьИзИсточникаДанных("Номенклатура", "Номенклатура");
ЭлементБлокировки.ИспользоватьИзИсточникаДанных("Склад", "Склад");
// Устанавливаем блокировку
Блокировка.Заблокировать();
// Только ПОСЛЕ этого выполняем запрос к остаткам
// ... Код запроса и проверки остатков ...
Проанализируем этот код: мы блокируем только те комбинации Номенклатура-Склад, которые присутствуют в текущем документе. Это позволяет другим пользователям беспрепятственно работать с другими товарами или складами.
Выясним причину возникновения взаимоблокировок даже в управляемом режиме. Если один документ сначала блокирует ТоварыНаСкладах, а затем ПартииТоваровНаСкладах, а другой документ делает это в обратном порядке — произойдет Deadlock.
Золотое правило: всегда блокируйте регистры в строго определенном алфавитном или логическом порядке во всех документах системы. Рассмотрим рекомендуемую последовательность для УТ 10.3:
РегистрНакопления.ТоварыНаСкладахРегистрНакопления.ТоварыВРозницеРегистрНакопления.ПартииТоваровНаСкладахВ тексте обсуждения упоминалась ошибка в функции ПолучитьДеревоПартийНаСкладахУпр. Проанализируем ситуацию: эта функция используется в УТ 10.3 для списания партий в режиме реального времени. Если вы перешли на управляемые блокировки, но не добавили код установки БлокировкаДанных внутри или перед вызовом этой функции, система будет пытаться читать данные, которые могут быть изменены другой транзакцией.
Для решения проблем с партионным учетом часто рекомендуют переписать механизмы на использование временных таблиц. Это позволяет подготовить все данные для списания заранее и заблокировать их одним вызовом, что существенно сокращает время удержания транзакции.
Для упрощения работы мы можем подсмотреть архитектурное решение в более тяжелых конфигурациях, таких как УПП 1.3 или КА 1.1. Там часто используется общая функция для установки блокировок. Рассмотрим пример реализации такого универсального механизма:
Процедура УстановитьУправляемуюБлокировку(ТаблицаДанных, ИмяРегистра) Экспорт
Блокировка = Новый БлокировкаДанных;
Элемент = Блокировка.Добавить(ИмяРегистра);
Элемент.Режим = РежимБлокировкиДанных.Исключительный;
Элемент.ИсточникДанных = ТаблицаДанных;
// Динамическое заполнение измерений
Для Каждого Колонка Из ТаблицаДанных.Колонки Цикл
Элемент.ИспользоватьИзИсточникаДанных(Колонка.Имя, Колонка.Имя);
КонецЦикла;
Блокировка.Заблокировать();
КонецПроцедуры
Использование подобных "оберток" позволит нам сократить количество дублируемого кода в модулях документов РеализацияТоваровУслуг, ПеремещениеТоваров, ТребованиеНакладная и других.
Подведем итог нашему исследованию. Перевод УТ 10.3 на управляемые блокировки — это не просто "галочка" в конфигураторе, а полноценная ревизия кода проведения. Основные усилия должны быть направлены на:
Соблюдение этих правил позволит вам добиться стабильной работы системы даже при круглосуточной нагрузке и большом штате операторов, исключив ошибки типа "Конфликт блокировок при выполнении транзакции".