Как устранить конфликт блокировок при удалении записи в независимом регистре сведений 1С?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При работе с базами данных 1С:Предприятие на платформе 8.2 и 8.3 (особенно в режиме обычных форм) специалисты часто сталкиваются с ситуацией, когда конкретную запись независимого регистра сведений невозможно удалить ни интерактивно, ни программно. Платформа выдает стандартную, но малоинформативную ошибку: «Конфликт блокировок при выполнении транзакции». Это может происходить даже при попытке просто открыть форму записи. В данной статье мы подробно разберем, почему возникают такие «фантомные» блокировки и как их устранить, используя системные инструменты 1С и SQL Server.

Выясним причину возникновения проблемы

Прежде чем приступать к активным действиям, давайте проанализируем ситуацию. Конфликт блокировок означает, что какой-то другой сеанс уже захватил эту область данных и удерживает её. В случае с независимым регистром сведений на SQL-базе блокировка может быть вызвана следующими факторами:

Метод 1. Диагностика через консоль администрирования кластера 1С

Рассмотрим самый простой способ идентификации виновника без остановки работы всех пользователей. Вместо радикальной перезагрузки сервера, мы можем точечно завершить проблемный сеанс.

Разберем по шагам работу в консоли администрирования:

  1. Откроем консоль администрирования кластеров 1С:Предприятия.
  2. Перейдем в раздел «Информационные базы» и выберем нашу базу.
  3. Зайдем в подраздел «Сеансы».
  4. Проанализируем колонку «Заблокировано СУБД». Если мы видим сеанс, который удерживает блокировку длительное время, это явный кандидат на завершение.
  5. Также обратим внимание на колонку «Разделитель данных» и время последней активности.

Если мы обнаружили «зависший» сеанс, его можно удалить принудительно. После этого блокировка на уровне СУБД должна сняться автоматически в течение нескольких секунд.

Метод 2. Использование средств SQL Server (SSMS)

Иногда консоль 1С не дает полной картины, особенно если блокировка «застряла» на уровне самого SQL-движка. В этом случае нам помогут инструменты SQL Server Management Studio (SSMS). Проанализируем ситуацию с помощью системных запросов.

Для быстрого поиска блокирующих процессов воспользуемся процедурой sp_who2. Выполним следующий скрипт в окне запросов:

EXEC sp_who2;

В колонке BlkBy мы увидим SPID (идентификатор процесса), который блокирует выполнение нашей команды. Если там стоит номер, значит, этот процесс мешает нам удалить запись.

Для более детального анализа используем динамические представления (DMV). Посмотрим на таблицу блокировок:


SELECT * FROM sys.dm_tran_locks
WHERE resource_database_id = DB_ID('Имя_Вашей_Базы');

Здесь мы можем увидеть тип блокировки (например, X — эксклюзивная, IX — намерение эксклюзивности) и конкретный объект. Если мы уверены, что процесс завис, его можно прервать командой KILL [SPID].

Метод 3. Программное удаление через Набор Записей

При работе с независимыми регистрами сведений важно правильно выбрать объект метаданных для удаления. Часто разработчики пытаются использовать РегистрСведенийМенеджерЗаписи. Однако метод МенеджерЗаписи.Прочитать() сам по себе может инициировать блокировку или столкнуться с ней.

Посмотрим на более надежный способ удаления через НаборЗаписей. Этот метод позволяет точечно очистить запись, установив фильтр по измерениям, не «вычитывая» саму запись в память целиком перед удалением.

Рассмотрим пример кода:


Набор = РегистрыСведений.НазваниеВашегоРегистра.СоздатьНаборЗаписей();
// Устанавливаем фильтры по ВСЕМ измерениям для точного попадания
Набор.Отбор.Измерение1.Установить(Значение1);
Набор.Отбор.Измерение2.Установить(Значение2);

// Записываем пустой набор (это удалит запись из базы)
// Параметр Ложь означает, что мы не замещаем весь регистр, а работаем только в рамках отбора
Набор.Записать(Истина); 

Использование Набор.Записать(Истина) с установленным отбором — это самый «чистый» способ удаления данных с точки зрения платформы 1С.

Метод 4. Прямое удаление через SQL (крайняя мера)

Если штатные средства 1С бессильны, а перезагрузка сервера невозможна, можно прибегнуть к удалению записи напрямую в SQL-таблице. Внимание: это опасная операция, требующая предварительного создания бэкапа!

Сначала выясним имя таблицы в SQL. Для этого в 1С выполним код:


Структура = ПолучитьСтруктуруХраненияБазыДанных();
// Проанализируем результат, чтобы найти таблицу для нужного регистра

Обычно таблицы регистров сведений называются _InfoRgXXXX. Найдя нужную таблицу и определив значения измерений, можно выполнить DELETE. Однако помните, что после такого удаления 1С может продолжать «видеть» запись в своем серверном кеше. В этом случае потребуется очистка кеша сервера или перезапуск службы 1C:Enterprise Server.

Подведем итоги

Конфликт блокировок в 1С 8.2 при удалении записи регистра обычно решается одним из следующих способов (в порядке возрастания сложности):

  1. Перезапуск службы 1С:Предприятия или SQL Server: Самый быстрый способ сбросить все зависшие транзакции, если позволяет регламент работы.
  2. Завершение конкретного сеанса: Через консоль администрирования 1С.
  3. Снятие процесса в SQL: Через Activity Monitor или команду KILL в SSMS.
  4. Программное удаление: Через объект РегистрСведенийНаборЗаписей с жестким фильтром по измерениям.

Чтобы минимизировать появление таких проблем в будущем, старайтесь избегать длительных транзакций и всегда проверяйте код на наличие избыточных блокировок в запросах (ДЛЯ ИЗМЕНЕНИЯ).

← На главную