Как исправить ошибку «Операция не может быть выполнена из-за несоответствия версии или отсутствия записи базы данных» в 1С?

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

При работе пользователей в программе 1С или при выполнении программного кода разработчики и системные администраторы нередко сталкиваются с сообщением: «Операция не может быть выполнена из-за несоответствия версии или отсутствия записи базы данных». Разберем детально природу этого явления, выясним, почему платформа выдает такое сообщение, и рассмотрим практические способы решения проблемы в различных сценариях.

Что означает данная ошибка: механизм оптимистической блокировки

По своей сути данное системное сообщение является не сбоем базы данных, а штатной защитой целостности данных, которая называется оптимистической блокировкой. Механизм встроен в ядро платформы 1С:Предприятие для всех ссылочных типов данных (справочники, документы, планы счетов, планы видов характеристик и др.).

Каждый ссылочный объект в базе данных имеет скрытый системный счетчик версий. Рассмотрим, как функционирует этот механизм:

  1. В момент открытия формы или считывания данных через метод ПолучитьОбъект() платформа фиксирует текущий номер версии объекта в памяти сеанса.
  2. Любая успешная запись объекта в базу данных (интерактивная, фоновая или программная) увеличивает системный счетчик версий на единицу.
  3. При попытке записать изменения из открытой формы или экземпляра объекта платформа сверяет зафиксированную ранее версию с текущей версией в таблице СУБД.
  4. Если версия в базе данных изменилась (стала новее), запись отменяется и генерируется исключение, предотвращающее перезапись чужих изменений устаревшими данными.

Важно отметить, что механизм версионирования действует только на ссылочные объекты. На регистры (сведений, накопления, бухгалтерии) оптимистическая блокировка не распространяется, так как у них нет объектной ссылки.

Причины возникновения коллизий в пользовательском интерфейсе

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

  1. Одновременное редактирование одного объекта двумя пользователями: если менеджер Иванов открыл карточку номенклатуры, а менеджер Петров открыл ту же карточку, изменил реквизит и нажал кнопку записи, то попытка Иванова сохранить свои правки вызовет ошибку несоответствия версии.
  2. Изменение открытого объекта фоновыми процессами или обработками: пользователь открыл документ, а в этот момент регламентное задание или внешняя обработка изменила реквизиты этого же документа в базе.
  3. Повреждение локального кэша пользователя: если ошибка возникает регулярно только на одном рабочем месте при создании или открытии новых элементов, причиной часто выступает некорректное состояние кэша метаданных и форм на стороне клиента.
  4. Двойной клик по кнопке сохранения: при высокой задержке сети пользователь может повторно нажать кнопку записи до завершения обработки первого запроса.

Типичные ошибки в программном коде 1С

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

Пример 1: Получение двух независимых экземпляров одного объекта в памяти

Если в коде дважды вызывается метод ПолучитьОбъект() для одной ссылки без синхронизации:


НомОбъект1 = НоменклатураСсылка.ПолучитьОбъект();
НомОбъект2 = НоменклатураСсылка.ПолучитьОбъект();

// Первый экземпляр успешно меняет версию в базе
НомОбъект2.Наименование = "Новое наименование";
НомОбъект2.Записать();

// Попытка записать первый экземпляр вызовет ошибку несоответствия версии
НомОбъект1.Артикул = "АРТ-001";
НомОбъект1.Записать();

Пример 2: Двойная запись в обработчиках событий формы

Вызов явного метода Записать() внутри процедур ПередЗаписью, ПриЗаписи или кнопках командной панели, когда параллельно отрабатывает стандартная системная команда сохранения формы.

Пример 3: Повторное получение объекта в подписках на события

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

Методы устранения и предотвращения ошибки

Разберем по шагам, как устранить ошибку в зависимости от причины её возникновения.

1. Действия пользователя в интерфейсе

Если ошибка возникла при интерактивном редактировании, выполним следующие действия:

  1. Закроем форму объекта без сохранения.
  2. Откроем форму заново, чтобы перечитать актуальную версию данных из базы.
  3. Повторно внесем нужные изменения и нажмем кнопку записи.

2. Очистка кэша на клиентском компьютере

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

  1. Завершим работу всех сеансов 1С на клиентском компьютере.
  2. Удалим содержимое каталогов %localappdata%\1C\1cv8 и %appdata%\1C\1cv8 (кроме файла ibases.v8i).
  3. Либо удалим базу из списка запуска 1С и добавим её заново, что создаст новую чистую директорию кэша.

3. Программная синхронизация через метод Прочитать()

Если объект уже находится в памяти и перед его изменением требуется обновить версию до актуального состояния в базе, применим метод Прочитать():


ОбъектСправочника = СсылкаНаОбъект.ПолучитьОбъект();

// Если возникло подозрение, что данные могли измениться
ОбъектСправочника.Прочитать();

ОбъектСправочника.Комментарий = "Актуализированные данные";
ОбъектСправочника.Записать();

4. Использование пессимистической блокировки

Чтобы исключить возможность параллельного редактирования важного документа другими сеансами на время интерактивной работы, используем метод ЗаблокироватьДанныеДляРедактирования() при открытии формы.

5. Обработка коллизий в фоновых обработках (паттерн повторных попыток)

При многопоточной пакетной обработке данных обернем попытку записи в конструкцию Попытка ... Исключение с переполучением объекта:


Успешно = Ложь;
ПопыткаСчетчик = 0;

Пока Не Успешно И ПопыткаСчетчик < 3 Цикл
    Попытка
        ОбъектДляЗаписи = Ссылка.ПолучитьОбъект();
        ОбъектДляЗаписи.Реквизит = НовоеЗначение;
        ОбъектДляЗаписи.Записать();
        Успешно = Истина;
    Исключение
        ПопыткаСчетчик = ПопыткаСчетчик + 1;
        Если ПопыткаСчетчик >= 3 Тогда
            ВызватьИсключение;
        КонецЕсли;
    КонецПопытки;
КонецЦикла;

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

← На главную