Ошибки блокировок — одна из самых распространенных и сложных проблем в высоконагруженных системах 1С. Они возникают, когда несколько пользователей одновременно пытаются изменить одни и те же данные, и система не может корректно распределить доступ к ресурсам. В рамках этой статьи мы проанализируем ситуацию, выясним причины возникновения конфликтов и разберем по шагам, как перевести систему на рельсы стабильной параллельной работы.
Прежде чем приступать к исправлению кода, нам необходимо понять, как 1С взаимодействует с СУБД (например, MS SQL Server или PostgreSQL). Существует два режима управления блокировками: автоматический и управляемый. В автоматическом режиме за блокировки отвечает СУБД, что часто приводит к избыточному захвату таблиц (блокируется вся таблица вместо конкретной строки). В управляемом режиме программист сам указывает, какие именно данные нужно заблокировать.
Для начала проанализируем ситуацию: если ваша конфигурация работает в режиме автоматических блокировок, первым шагом к решению проблемы будет перевод метаданных в режим Управляемый. Это позволит системе накладывать блокировки только на уровне записей, значительно повышая параллельность работы пользователей.
Чтобы точно понять, какой объект вызывает проблему, нам нужно настроить Технологический Журнал (ТЖ). Это мощный инструмент диагностики, который фиксирует все события в системе. Нас интересуют события TLOCK (ожидание блокировки) и TTIMEOUT (превышение времени ожидания).
Рассмотрим пример настройки файла logcfg.xml для отлова конфликтов блокировок:
<config xmlns="http://v8.1c.ru/v8/config/logcfg">
<log location="C:\Logs\Locks" history="72">
<event>
<eq property="Name" value="TLOCK"/>
</event>
<event>
<eq property="Name" value="TTIMEOUT"/>
</event>
<property name="all"/>
</log>
</config>
Проанализировав лог-файлы, мы сможем увидеть, какая именно транзакция удерживала ресурсы слишком долго и какой пользователь стал «жертвой» блокировки.
Перейдем к практической части. Для того чтобы минимизировать вероятность конфликтов, мы должны использовать объект БлокировкаДанных. Его следует применять непосредственно перед началом выполнения запросов на чтение или запись данных в транзакции. Посмотрим на пример реализации блокировки остатков товаров при проведении документа:
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.ТоварыНаСкладах");
// Устанавливаем режим блокировки - Исключительный (для записи)
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
// Указываем конкретные значения измерений, которые нужно заблокировать
ЭлементБлокировки.УстановитьЗначение("Склад", СсылкаНаСклад);
ЭлементБлокировки.ИсточникДанных = СписокТоваров;
ЭлементБлокировки.ИспользоватьИзИсточникаДанных("Номенклатура", "Номенклатура");
// Выполняем блокировку
Блокировка.Заблокировать();
В этом примере мы блокируем не весь регистр ТоварыНаСкладах, а только те комбинации Склад + Номенклатура, которые присутствуют в нашем документе. Это позволяет другим пользователям одновременно проводить документы по другим складам или товарам без каких-либо задержек.
Важно помнить: чем дольше длится транзакция, тем выше риск конфликта. Рассмотрим основные правила оптимизации, которые помогут нам сократить время удержания блокировок:
Записать() или начала процедуры ОбработкаПроведения.Склады, затем регистр ТоварыНаСкладах). Это поможет избежать ситуации «Deadlock» (взаимная блокировка), когда два процесса ждут друг друга.Для баз данных на MS SQL Server критически важным является включение режима Read Committed Snapshot Isolation (RCSI). Этот механизм позволяет 1С читать данные без установки блокировок на чтение, используя версии строк. Это радикально снижает количество конфликтов между отчетами и проведением документов.
Чтобы проверить и включить этот режим, используйте следующие SQL-команды (выполняются администратором БД):
-- Проверка текущего статуса
SELECT name, is_read_committed_snapshot_on FROM sys.databases WHERE name = 'ИмяВашейБазы';
-- Включение режима (требует отсутствия активных соединений)
ALTER DATABASE [ИмяВашейБазы] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
ALTER DATABASE [ИмяВашейБазы] SET READ_COMMITTED_SNAPSHOT ON;
ALTER DATABASE [ИмяВашейБазы] SET MULTI_USER;
Мы рассмотрели подробнее архитектуру блокировок и выяснили причину типичных ошибок производительности. Подводя итог, можно выделить следующий алгоритм действий для избавления от конфликтов блокировок:
БлокировкаДанных в коде для точечного захвата ресурсов.Read Committed Snapshot на стороне СУБД.Соблюдение этих правил позволит вашей системе 1С работать быстро и стабильно даже при одновременной работе сотен пользователей.