Почему возникает ошибка «Объект заблокирован» при проведении чека ККМ в 1С 7.7 и как ее исправить?

Программист 1С v7.7 Управленческий учет Торговля и дистрибуция
← На главную

Работа с торговым оборудованием в старых версиях 1С, таких как «Торговля и Склад 7.7», часто сопровождается трудноуловимыми ошибками блокировок. Особенно остро проблема проявляется в клиент-серверном варианте (на MS SQL Server), когда количество одновременно работающих касс увеличивается. Ошибка Объект заблокирован! при попытке выполнить метод Провести() — это классический признак конфликта транзакций или нарушения логики работы с объектом базы данных.

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

Причина 1: Рекурсивный вызов метода Провести() в модуле формы

Проанализируем предоставленный код. Основная ошибка кроется в месте вызова проведения. Если метод Провести() вызывается внутри предопределенной процедуры ПриЗаписи(), система попадает в «ловушку» блокировок. В 1С 7.7 момент записи документа уже открывает транзакцию и накладывает блокировку на запись в таблице журналов (_1SJOURN) и таблице самого документа.

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

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


Процедура ПриЗаписи()
    // ОПАСНО: Вызов проведения внутри записи
    Если Провести() = 1 Тогда 
        // Логика печати чека
    КонецЕсли;
КонецПроцедуры

Как исправить: Необходимо вынести логику проведения за пределы процедуры ПриЗаписи(). Проведение должно запускаться либо интерактивно пользователем, либо через обработку ожидания, либо программно, но строго после того, как документ был записан и основная транзакция закрыта.

Причина 2: Длительные транзакции при оплате картой

Выясним, почему ошибка чаще возникает при безналичном расчете. Процесс оплаты картой обычно выглядит так:

  1. Программа инициирует проведение документа.
  2. 1С отправляет запрос на эквайринговый терминал.
  3. Система ждет ответа от банка (это может занимать от 5 до 30 секунд).
  4. После успешного ответа завершается проведение и печатается чек.

Проблема в том, что все это время (пока кассир вставляет карту или клиент вводит ПИН-код) транзакция в SQL остается открытой. В 1С 7.7 при проведении чека блокируются таблицы итогов регистров (например, остатки товаров и денежные средства). Если в магазине работают 3-4 кассы, и на одной из них «зависла» оплата по карте, остальные кассы не смогут провести даже обычный наличный чек, так как будут ждать освобождения таблиц остатков. В итоге система выдает ошибку Объект заблокирован или Lock timeout expired.

Решение: Разделите процесс. Сначала выполняйте авторизацию карты (взаимодействие с терминалом), и только при получении положительного ответа запускайте проведение документа 1С. Это сократит время удержания блокировок до миллисекунд.

Причина 3: Особенности SQL-версии и сетевого доступа

Проанализируем ситуацию с сетевым окружением. Если база данных расположена на SQL-сервере, но доступ к исполняемым файлам или компонентам осуществляется через «расшаренную» папку (SMB), это вносит дополнительные задержки.

Важно проверить настройку Lock Timeout на SQL-сервере. Если время ожидания блокировки установлено в 0 или слишком малое значение, 1С будет «вылетать» с ошибкой сразу же, как только столкнется с занятым ресурсом, не пытаясь подождать его освобождения даже долю секунды.

Также обратите внимание на способ обращения к документу в коде. Как было отмечено в обсуждении, ошибка часто возникает, если используется позиционирование (НайтиДокумент) вместо работы через прямой контекст. Рассмотрим правильный подход к передаче контекста в процедуры проведения:


// В модуле документа
Процедура ОбработкаПроведения()
    // Передаем Контекст текущего объекта в общие процедуры
    ДвиженияРегистровНакладных(Контекст);
    ДвиженияРегистровОрдеров(Контекст);
КонецПроцедуры

Использование Контекст гарантирует, что процедуры работают именно с теми данными, которые сейчас находятся в памяти транзакции, не пытаясь перечитать их из базы «со стороны», что и вызывает блокировку.

Рекомендации по устранению проблемы:

  1. Оптимизация метода проведения: Проверьте процедуры ДвиженияРегистровНакладных и ДвиженияРегистровОрдеров. В них не должно быть сложных запросов или циклов, которые обращаются к сторонним документам. Все данные для проведения должны быть подготовлены заранее.
  2. Настройка ожидания блокировок: Увеличьте время ожидания блокировки в настройках SQL Server (параметр LOCK_TIMEOUT). Для 1С 7.7 оптимально установить значение порядка 15000–30000 мс (15-30 секунд).
  3. Использование флага проведения: В форме документа вместо прямого вызова Провести() используйте программное нажатие кнопки «ОК» или вызов функции через Форма.ОбработкаОжидания(), чтобы проведение гарантированно началось в «чистом» контексте, когда форма уже готова к закрытию.
  4. Отключение Oplocks: Если часть файлов базы (даже в SQL-варианте, например, словари .DDS) доступна через сеть, убедитесь, что на сервере отключены Opportunistic Locking (Oplocks). Это предотвратит «фантомные» блокировки файлов сетевым протоколом Windows.

Таким образом, для решения проблемы «Объект заблокирован» в 1С 7.7 необходимо прежде всего разорвать связь между интерактивной записью объекта и его проведением, а также минимизировать время ожидания внешних событий (таких как ответ банковского терминала) внутри транзакции 1С.

← На главную