При сопровождении устаревших конфигураций, таких как 1С:Бухгалтерия предприятия 2.0 КОРП, разработчики часто сталкиваются с необходимостью повышения режима совместимости. Чаще всего это продиктовано требованиями современной интеграции (например, заполнение контрагентов по ИНН данными ФНС или обмен с SAP через XDTO), так как старые версии платформы могут некорректно обрабатывать сложные схемы XML, специфические типы данных или выполнять обновление контрагента по ИНН. Однако простое изменение свойства конфигурации "Режим совместимости" с 8.2.16 на 8.3.9 и выше мгновенно вскрывает архитектурные проблемы кода, который десятилетиями работал стабильно.
В этой статье мы подробно разберем одну из самых коварных ошибок (подобно тому, как исправляли реестр документов с автоматическим заполнением), возникающих при таком переходе: "Использование блокировки допустимо только внутри транзакции в режиме управляемых блокировок!". Мы выясним причины её появления на примере документа "Авизо" и рассмотрим пошаговые инструкции по исправлению.
Проанализируем ситуацию. В режиме совместимости 8.2.16 платформа 1С допускала более мягкое отношение к вызову метода Заблокировать() объекта УправляемаяБлокировка (или DataLock). Если в конфигурации использовался смешанный режим или автоматические блокировки, платформа могла проигнорировать отсутствие явной транзакции при некоторых условиях.
Начиная с режима совместимости 8.3.x, логика становится жесткой: если в свойствах конфигурации установлен "Режим управления блокировкой данных" — Управляемый, то любой программный вызов метода Заблокировать() обязан находиться внутри транзакции. Транзакция может быть открыта платформой автоматически (например, в обработке проведения документа) или программно разработчиком.
В случае с документом "Авизо" в БП 2.0 ошибка возникает при нажатии кнопки "Заполнить". Процедура заполнения вызывает механизмы партионного учета, чтобы рассчитать остатки и подготовить данные (в этот момент полезно исправить пересортицу на 41 счете). Эти механизмы содержат код для установки блокировок (чтобы данные не изменились в процессе расчета), но так как это просто нажатие кнопки на форме, а не проведение документа, автоматическая транзакция не открывается. Программа пытается установить управляемую блокировку "в пустоте", что и приводит к авариной остановке.
Первый и самый очевидный способ решения — обеспечить наличие транзакции в том месте, где вызывается расчет партий. Рассмотрим, как это реализовать в коде формы или модуля документа. Нам необходимо найти процедуру, указанную в стеке ошибки (в нашем случае это ЗаполнитьДанныеПоПартиям), и модифицировать её.
Разберем пример кода, который позволит избежать ошибки:
Процедура ЗаполнитьДанныеПоПартиям()
// Начинаем транзакцию, так как внутри вызываются механизмы с управляемыми блокировками
НачатьТранзакцию();
Попытка
// Вызываем типовой механизм списания/расчета партий
УправлениеЗапасамиПартионныйУчет.ДвижениеПартийТоваров(
Заголовок,
ТаблицаПоТоварам,
Истина,
Ложь,
Отказ,
,
"Передача товаров",
Ложь
);
// Если все прошло успешно, фиксируем транзакцию
ЗафиксироватьТранзакцию();
Исключение
// В случае ошибки обязательно отменяем транзакцию
ОтменитьТранзакцию();
// Выводим сообщение пользователю
ОбщегоНазначения.СообщитьОбОшибке(ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Важный нюанс: использование транзакции при простом заполнении формы может привести к кратковременным блокировкам таблиц базы данных для других пользователей. В системе с 2000 активных сессий это может стать критичным, поэтому транзакция должна быть максимально короткой.
Проанализируем свойства метаданных. Часто в старых базах встречается "зоопарк" настроек: конфигурация стоит в режиме "Управляемый", а конкретные объекты (например, регистр Хозрасчетный) — в режиме "Автоматический". В режиме совместимости 8.3 это сочетание работает крайне неэффективно.
Если вы решили переходить на режим 8.3.9, необходимо выполнить следующие действия:
Управляемый.Хозрасчетный, ПартииТоваровНаСкладах, БухгалтерскиеВзаиморасчеты) также установить свойство "Режим управления блокировкой данных" в значение Управляемый.БлокировкаДанных, проверить, что все пространства блокировок соответствуют типам объектов, у которых включен управляемый режим.Посмотрим на пример установки блокировки, который часто вызывает сбой в ОбщийМодуль.ОбщегоНазначения:
ЭлементБлокировки = Блокировка.Добавить("РегистрБухгалтерии.Хозрасчетный");
ЭлементБлокировки.УстановитьЗначение("Организация", Организация);
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
Блокировка.Заблокировать(); // Ошибка будет здесь, если нет транзакции
Если регистр Хозрасчетный остается в автоматическом режиме, попытка установить на него РежимБлокировкиДанных.Исключительный в управляемом режиме может вести себя непредсказуемо на новой платформе.
Третий вариант — самый трудоемкий, но наиболее правильный с точки зрения производительности для крупных систем. Суть заключается в том, чтобы разделить логику чтения данных для заполнения ТЧ и логику блокировки данных для записи.
Проанализируем ситуацию: зачем нам блокировать итоги регистра, если мы просто хотим заполнить табличную часть документа на форме? Блокировка нужна при записи и проведении, чтобы гарантировать неизменность остатков. При нажатии кнопки "Заполнить" достаточно получить текущие данные (пусть даже они изменятся через секунду).
Для реализации этого подхода нужно:
ДвижениеПартийТоваров, специально предназначенную для режима "Только чтение".УстановитьУправляемуюБлокировку.Работа 2000 пользователей в БП 2.0 на платформе 8.3 с высоким режимом совместимости — это серьезный вызов. Рассмотрим основные риски, которые нужно учесть:
1. Деградация производительности запросов. Платформа 8.3 иначе строит планы запросов к SQL-серверу, особенно при использовании временных таблиц. После повышения режима совместимости обязательно выполните замер производительности ключевых операций (проведение документов, формирование ОСВ).
2. Изменение работы XDTO. Хотя повышение совместимости решило проблему с SAP, оно может сломать другие интеграции, которые опирались на специфическое (иногда ошибочное) поведение парсера XML в версии 8.2.
3. Объекты с автоматическими блокировками. В режиме совместимости 8.3 "смешанный" режим блокировок (когда часть объектов управляемые, а часть автоматические) работает медленнее из-за того, что СУБД приходится накладывать блокировки самого высокого уровня, чтобы обеспечить целостность. Постарайтесь перевести все регистры в режим управляемых блокировок.
Выясним, стоит ли вообще игра свеч. Если единственная цель — работа с SAP, иногда проще вынести логику обмена во внешнюю обработку или отдельную буферную базу на платформе 8.3 с высокой совместимостью, которая будет транслировать данные в БП 2.0, не трогая основной режим совместимости конфигурации.
Таким образом, мы рассмотрели основные пути решения проблемы. Самым быстрым "костылем" является использование НачатьТранзакцию(), но для стабильной работы системы на 2000 рабочих мест мы рекомендуем провести полный аудит режимов блокировок всех регистров и рефакторинг процедур заполнения.