При работе пользователей в программе 1С или при выполнении программного кода разработчики и системные администраторы нередко сталкиваются с сообщением: «Операция не может быть выполнена из-за несоответствия версии или отсутствия записи базы данных». Разберем детально природу этого явления, выясним, почему платформа выдает такое сообщение, и рассмотрим практические способы решения проблемы в различных сценариях.
По своей сути данное системное сообщение является не сбоем базы данных, а штатной защитой целостности данных, которая называется оптимистической блокировкой. Механизм встроен в ядро платформы 1С:Предприятие для всех ссылочных типов данных (справочники, документы, планы счетов, планы видов характеристик и др.).
Каждый ссылочный объект в базе данных имеет скрытый системный счетчик версий. Рассмотрим, как функционирует этот механизм:
ПолучитьОбъект() платформа фиксирует текущий номер версии объекта в памяти сеанса.Важно отметить, что механизм версионирования действует только на ссылочные объекты. На регистры (сведений, накопления, бухгалтерии) оптимистическая блокировка не распространяется, так как у них нет объектной ссылки.
Проанализируем типичные ситуации, когда пользователь сталкивается с ошибкой при обычной работе в программе:
В процессе доработки конфигураций программисты могут непреднамеренно вызвать ошибку несоответствия версии. Посмотрим на классические примеры некорректной реализации алгоритмов.
Пример 1: Получение двух независимых экземпляров одного объекта в памяти
Если в коде дважды вызывается метод ПолучитьОбъект() для одной ссылки без синхронизации:
НомОбъект1 = НоменклатураСсылка.ПолучитьОбъект();
НомОбъект2 = НоменклатураСсылка.ПолучитьОбъект();
// Первый экземпляр успешно меняет версию в базе
НомОбъект2.Наименование = "Новое наименование";
НомОбъект2.Записать();
// Попытка записать первый экземпляр вызовет ошибку несоответствия версии
НомОбъект1.Артикул = "АРТ-001";
НомОбъект1.Записать();
Пример 2: Двойная запись в обработчиках событий формы
Вызов явного метода Записать() внутри процедур ПередЗаписью, ПриЗаписи или кнопках командной панели, когда параллельно отрабатывает стандартная системная команда сохранения формы.
Пример 3: Повторное получение объекта в подписках на события
В обработчике подписки на событие ПередЗаписью объекта разработчик ошибочно обращается к базе через Источник.Ссылка.ПолучитьОбъект() и записывает его, вместо непосредственной модификации переданного параметра Источник.
Разберем по шагам, как устранить ошибку в зависимости от причины её возникновения.
1. Действия пользователя в интерфейсе
Если ошибка возникла при интерактивном редактировании, выполним следующие действия:
2. Очистка кэша на клиентском компьютере
Если сбой происходит у конкретного пользователя на пустых или новых элементах, очистим временные файлы 1С:
%localappdata%\1C\1cv8 и %appdata%\1C\1cv8 (кроме файла ibases.v8i).3. Программная синхронизация через метод Прочитать()
Если объект уже находится в памяти и перед его изменением требуется обновить версию до актуального состояния в базе, применим метод Прочитать():
ОбъектСправочника = СсылкаНаОбъект.ПолучитьОбъект();
// Если возникло подозрение, что данные могли измениться
ОбъектСправочника.Прочитать();
ОбъектСправочника.Комментарий = "Актуализированные данные";
ОбъектСправочника.Записать();
4. Использование пессимистической блокировки
Чтобы исключить возможность параллельного редактирования важного документа другими сеансами на время интерактивной работы, используем метод ЗаблокироватьДанныеДляРедактирования() при открытии формы.
5. Обработка коллизий в фоновых обработках (паттерн повторных попыток)
При многопоточной пакетной обработке данных обернем попытку записи в конструкцию Попытка ... Исключение с переполучением объекта:
Успешно = Ложь;
ПопыткаСчетчик = 0;
Пока Не Успешно И ПопыткаСчетчик < 3 Цикл
Попытка
ОбъектДляЗаписи = Ссылка.ПолучитьОбъект();
ОбъектДляЗаписи.Реквизит = НовоеЗначение;
ОбъектДляЗаписи.Записать();
Успешно = Истина;
Исключение
ПопыткаСчетчик = ПопыткаСчетчик + 1;
Если ПопыткаСчетчик >= 3 Тогда
ВызватьИсключение;
КонецЕсли;
КонецПопытки;
КонецЦикла;
Применение этих правил позволяет корректно выстроить архитектуру взаимодействия с базой данных, исключить потерю информации и предотвратить появление ошибок блокировок версий.