Почему в 1С 7.7 (SQL) возникает ошибка "Объект заблокирован" и как это исправить?

Программист 1С v7.7
← На главную

Столкнулись с ситуацией, когда в многопользовательской SQL-базе 1С:Предприятие 7.7 пользователи не могут программно записать справочник или провести документ? Система выдает сообщение "Объект заблокирован", хотя сам объект никто не открывал в интерактивном режиме. Часто проблема проявляется под одним конкретным пользователем, и временным решением становится перезапуск его сеанса 1С. Давайте вместе разберемся в причинах этой проблемы и найдем надежное решение.

Проанализируем ситуацию: ошибка возникает при программной работе с объектами, база данных работает под управлением MS SQL Server. Это ключевые моменты, которые указывают на то, что проблема, скорее всего, лежит глубже, чем просто открытая пользователем форма.

Два уровня блокировок: 1С и SQL Server

Для начала важно понять, что в SQL-версии 1С 7.7 мы имеем дело с двумя системами блокировок, работающими одновременно:

  1. Блокировки уровня 1С. Это механизм самой платформы. Когда вы открываете документ для редактирования, 1С создает специальную блокировку на уровне приложения. Информация о ней может храниться во временных файлах (*.LCK). Обычно такие блокировки возникают при интерактивной работе и снимаются при закрытии формы.
  2. Блокировки уровня SQL Server. Это фундаментальный механизм СУБД для управления одновременным доступом к данным. Любая операция, изменяющая данные (запись, проведение), выполняется внутри SQL-транзакции. На время ее выполнения SQL Server блокирует таблицы или строки, к которым идет обращение.

Сообщение "Объект заблокирован" в нашем случае — это чаще всего интерпретация платформой 1С долгого ожидания снятия именно транзакционной блокировки на уровне SQL Server. Один пользователь начал операцию, "захватил" данные, а все остальные ждут, пока он их "отпустит".

Основная причина: незавершенная транзакция

Самой вероятной причиной "зависших" блокировок является незавершенная транзакция в коде 1С. Проанализируем, как это происходит. В коде 1С для выполнения группы операций как единого целого используется пара команд: НачатьТранзакцию() и ЗафиксироватьТранзакцию().

Если программист запустил транзакцию командой НачатьТранзакцию(), а до команды ЗафиксироватьТранзакцию() дело не дошло (например, из-за ошибки в коде или сбоя), то эта транзакция "зависает" на сервере SQL. Сессия пользователя в 1С может выглядеть неактивной, но его соединение с SQL Server продолжает удерживать все блокировки, установленные в рамках этой транзакции. Эти блокировки будут удерживаться бесконечно долго, пока сессия не будет принудительно завершена.

Любой другой пользователь, который попытается обратиться к заблокированным данным (например, провести документ, который двигает те же регистры), будет поставлен в очередь ожидания. Для 1С это ожидание выглядит как блокировка объекта.

Почему транзакция может не завершиться?

Диагностика блокировок на уровне SQL Server: пошаговая инструкция

Чтобы найти источник проблемы, нам нужно заглянуть "под капот" и посмотреть, что происходит на сервере SQL. Для этого понадобится доступ к MS SQL Server Management Studio (SSMS).

Шаг 1: Находим блокирующую сессию

Стандартная команда sp_lock показывает наличие блокировок, но не дает полной картины. Гораздо удобнее использовать системную процедуру sp_who2. Она показывает все активные процессы на сервере.

Выполните в SSMS следующий запрос:


sp_who2

В результате вы увидите таблицу со списком всех сессий. Нас интересует столбец BlkBy (Blocked By). Если у какой-то строки в этом столбце стоит номер (например, "58"), это означает, что данный процесс (сессия) заблокирован процессом с SPID 58. SPID — это уникальный идентификатор сессии, он находится в первом столбце.

Теперь найдите в списке строку, у которой SPID равен 58. Это и есть "виновник" — сессия, которая удерживает блокировку.

Шаг 2: Идентифицируем пользователя-источника блокировки

После того как мы нашли блокирующую сессию (SPID), нужно понять, кто ее запустил. Посмотрите на ту же строку в выводе sp_who2. Нам помогут столбцы:

Если пользователи работают не на терминальном сервере, этих данных обычно достаточно, чтобы найти компьютер и пользователя, сеанс которого вызвал проблему.

В терминальной среде все сессии будут исходить от одного сервера. В этом случае для точной идентификации пользователя 1С можно использовать более продвинутые методики, например, создать в SQL специальную таблицу, куда при старте сеанса 1С будет записываться связка "Имя пользователя 1С — SPID соединения".

Шаг 3: Экстренное снятие блокировки

Когда "виновник" найден и нужно срочно восстановить работу остальных пользователей, можно принудительно завершить его сессию на SQL Server. Для этого используется команда KILL.

Внимание! Используйте эту команду с осторожностью. Она аварийно прервет сессию пользователя, все его незаписанные данные будут потеряны.


KILL 58 -- Где 58 - это SPID блокирующей сессии

После выполнения этой команды SQL Server автоматически отменит незавершенную транзакцию, снимет все блокировки, и другие пользователи смогут продолжить работу. Однако это лишь временное решение. Проблема вернется, если не устранить ее первопричину.

Поиск и устранение первопричины в коде 1С

Теперь самое главное — найти в конфигурации 1С место, где транзакция не завершается. Основное правило, которое должно соблюдаться неукоснительно:

Любой вызов НачатьТранзакцию() должен находиться внутри конструкции Попытка ... Исключение ... КонецПопытки.

Правильная структура кода выглядит так:


Процедура ПровестиДокумент()
    // ... какая-то подготовительная логика ...

    Попытка
        НачатьТранзакцию();

        // Основной код проведения:
        // Движения по регистрам, запись связанных объектов и т.д.
        
        ЗафиксироватьТранзакцию();
        Возврат 1; // Успешное завершение

    Исключение
        ОтменитьТранзакцию();
        Сообщить("Не удалось провести документ! " + ОписаниеОшибки());
        Возврат 0; // Неуспешное завершение
    КонецПопытки;

КонецПроцедуры

В этом примере, если внутри блока между НачатьТранзакцию() и ЗафиксироватьТранзакцию() произойдет любая ошибка, выполнение перейдет в секцию Исключение, где команда ОтменитьТранзакцию() гарантированно отменит транзакцию и освободит все блокировки.

Ваша задача — провести ревизию кода конфигурации. Ищите все вхождения НачатьТранзакцию() и проверяйте, что они обернуты в такую безопасную конструкцию.

Косвенные причины: сеть и обновления ОС

Иногда причина незавершенной транзакции не в коде, а во внешней среде. Разрыв соединения между клиентом и сервером может оставить "висячую" сессию на SQL Server.

Если вы уверены в коде, проверьте стабильность сетевого подключения на машине проблемного пользователя и настройки безопасности операционной системы.

← На главную