Одной из наиболее часто встречающихся и в то же время сложных в диагностике проблем в многопользовательских системах 1С является конфликт блокировок. Эта ситуация возникает, когда несколько сеансов одновременно пытаются получить доступ к одним и тем же данным в режиме записи или исключительного чтения. В данной статье мы подробно разберем, почему возникают блокировки, как их диагностировать и какими программными методами можно свести количество конфликтов к минимуму.
Для начала проанализируем ситуацию с точки зрения архитектуры базы данных. Когда 1С выполняет запись в базу (например, проведение документа), она открывает транзакцию. Чтобы данные оставались целостными, система «замораживает» (блокирует) определенные записи в таблицах SQL или файловой базе. Если другой пользователь в этот же момент хочет изменить те же данные, он встает в очередь. Если ожидание превышает установленный лимит (обычно 20 секунд), пользователь получает сообщение об ошибке.
Рассмотрим основные причины возникновения конфликтов:
Разберем по шагам, как современная платформа 1С 8.3 позволяет управлять этим процессом. Первым и самым важным шагом является установка режима Управляемый в свойствах конфигурации. В этом режиме разработчик сам указывает системе, какие данные нужно заблокировать перед началом изменений.
Для этого используется объект БлокировкаДанных. Проанализируем пример кода, который позволяет заблокировать остатки по конкретному складу, чтобы исключить конкурентный доступ других пользователей при расчете списания:
// Создаем объект блокировки
ЭлементБлокировки = Новый БлокировкаДанных;
НоваяБлокировка = ЭлементБлокировки.Добавить("РегистрНакопления.ОстаткиНоменклатуры");
// Устанавливаем режим блокировки - Исключительный (для записи)
НоваяБлокировка.Режим = РежимБлокировкиДанных.Исключительный;
// Указываем конкретные измерения, по которым будет установлена блокировка
НоваяБлокировка.УстановитьЗначение("Склад", СсылкаНаСклад);
НоваяБлокировка.УстановитьЗначение("Номенклатура", ВыбранныйТовар);
// Выполняем блокировку в рамках транзакции
ЭлементБлокировки.Заблокировать();
Важный нюанс: вызов метода Заблокировать() должен происходить строго внутри транзакции (между НачатьТранзакцию() и ЗафиксироватьТранзакцию() или в процедурах ОбработкаПроведения).
Выясним причину, по которой даже при использовании управляемых блокировок могут возникать конфликты. Часто программисты допускают ошибку, выполняя тяжелые запросы на чтение данных уже после того, как были установлены блокировки на запись. Рассмотрим правильную последовательность действий:
Посмотрим на пример правильной структуры кода в модуле набора записей или документа:
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
// 1. Подготовка данных: выгружаем товары в таблицу значений
ТаблицаТоваров = ЭтотОбъект.Товары.Выгрузить();
ТаблицаТоваров.Свернуть("Номенклатура", "Количество");
// 2. Установка управляемой блокировки
Блокировка = Новый БлокировкаДанных;
Элемент = Блокировка.Добавить("РегистрНакопления.ОстаткиНоменклатуры");
Элемент.Режим = РежимБлокировкиДанных.Исключительный;
Элемент.ИсточникДанных = ТаблицаТоваров;
Элемент.ИспользоватьИзИсточникаДанных("Номенклатура", "Номенклатура");
Блокировка.Заблокировать();
// 3. Теперь выполняем запрос к остаткам - данные гарантированно не изменятся другими пользователями
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ Остатки.Номенклатура, Остатки.КоличествоОстаток ...";
// ... выполнение запроса и логика списания
КонецПроцедуры
Если проблема уже существует в рабочей базе, нам необходимо выяснить, какой именно код вызывает избыточное ожидание. Рассмотрим основные инструменты:
1. Консоль анализа блокировок. Это стандартная обработка (часто входит в состав БСП или инструментов разработчика), которая показывает текущие активные блокировки в разрезе сеансов и таблиц базы данных.
2. Технологический журнал (ТЖ). Это самый мощный инструмент. Для поиска блокировок нужно настроить сбор событий TLOCK, TTIMEOUT и TDEADLOCK. В файле настроек logcfg.xml мы можем указать параметры для отслеживания только тех ожиданий, которые длятся более 5-10 секунд.
3. Монитор активности в SQL Server Management Studio. Если вы используете клиент-серверный вариант, полезно посмотреть на процесс со стороны СУБД. Обратите внимание на колонку Wait Type (тип ожидания) и Blocking Hierarchy (кто кого блокирует).
Проанализируем еще несколько стратегий, которые помогут сделать работу пользователей более комфортной:
Борьба с конфликтами блокировок — это всегда баланс между скоростью работы одного пользователя и пропускной способностью системы в целом. Переход на управляемый режим, грамотное использование объекта БлокировкаДанных и анализ технологического журнала позволяют практически полностью исключить ошибки типа «Конфликт блокировок» даже в высоконагруженных системах с сотнями одновременно работающих сотрудников.
Помните, что блокировка — это не ошибка, а защитный механизм платформы. Наша задача как разработчиков — сделать так, чтобы этот механизм работал точечно, быстро и незаметно для конечного пользователя.