Работа в распределенных информационных базах (РИБ) часто преподносит неприятные сюрпризы в виде сбоев при синхронизации данных между главным и подчиненными узлами. В рамках данной статьи мы подробно разберем две критические ошибки, которые полностью блокируют процесс обмена данными, выясним причины их возникновения и найдем проверенные практические способы их решения.
---
Первая техническая проблема возникает в момент чтения файла сообщения обмена на этапе фиксации транзакции. Платформа выдает ошибку, которая выглядит следующим образом:
Ошибка при вызове метода контекста (ЗакончитьЧтение): Ошибка при выполнении обработчика - 'ПередЗаписью'... Запись с такими ключевыми полями существует! : СтоимостьТоваров...
Эта ошибка означает, что система пытается записать в регистр сведений строку, у которой набор ключевых полей (измерений, а для периодических регистров — еще и даты/периода) полностью совпадает с уже существующей записью в принимающей базе данных. При этом платформа не может перезаписать старую строку из-за отсутствия флага замещения или конфликта уникальных идентификаторов (GUID) документов-регистраторов.
Рассмотрим пошагово четыре метода устранения этой проблемы.
Если ошибка локальная и содержит указание на конкретную номенклатуру, склад и дату, мы можем найти эту запись непосредственно в информационной базе и удалить её, чтобы дать обмену успешно завершиться.
Выполним следующие действия:
Стоимость товаров).Чаще всего записи в регистре Стоимость товаров генерируются автоматически регламентными документами закрытия месяца. Самый простой и корректный способ исправить движения в автоматическом режиме — это перепровести первичный документ.
Выполним этот процесс по шагам:
Расчет себестоимости товаров (или аналогичный документ закрытия месяца/периода) за дату, указанную в ошибке (в нашем случае — январь 2014 года).Стоимость товаров.Расчет себестоимости товаров и проведем его заново, чтобы восстановить актуальные движения и восстановить последовательность партионного учета.Если мы являемся разработчиками конфигурации и хотим исключить повторение подобной ошибки в будущем, нам необходимо убедиться, что запись в регистр в процедурах обмена или при проведении документов всегда выполняется с установленным свойством замещения существующих записей.
Проанализируем пример кода, который гарантирует корректную запись без вызова конфликта дублирования ключевых полей:
НаборЗаписей = РегистрыСведений.СтоимостьТоваров.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Период.Установить(ВыбранныйПериод);
НаборЗаписей.Отбор.Номенклатура.Установить(ВыбранныйТовар);
НаборЗаписей.Отбор.Склад.Установить(ВыбранныйСклад);
// Обязательно считываем текущее состояние регистра
НаборЗаписей.Прочитать();
// Очищаем старые записи при необходимости или модифицируем их
НаборЗаписей.Очистить();
// Записываем набор с флагом замещения (Истина)
НаборЗаписей.Записать(Истина);
---
Вторая техническая проблема часто возникает в подчиненных узлах во время применения изменений. Ошибка выглядит следующим образом:
Ошибка при вызове метода контекста (ПрочитатьИзменения): Ошибка при выполнении обработчика - 'ПередЗаписью': ... Модуль(1552): Ошибка при вызове метода контекста (ЗарегистрироватьИзменения): Недопустимое значение параметра (параметр номер '2')
Второй параметр метода ПланыОбмена.ЗарегистрироватьИзменения() принимает объект или ссылку на объект, изменения которого мы хотим отправить. Данная ошибка возникает по следующим причинам:
<Объект не найден>, которое метод регистрации обработать не может.ПередЗаписью() для нового элемента, у которого еще нет ссылки в базе.Рассмотрим способы устранения этой ошибки.
Наиболее частая причина появления некорректного параметра — это логическая несогласованность базы данных («битые» ссылки). Для их устранения запустим процедуру тестирования информационной базы:
Вторая распространенная причина — срабатывание лишних механизмов регистрации изменений при загрузке данных РИБ. Например, когда подчиненный узел принимает документы из центральной базы, срабатывает подписка на события общего модуля (например, ОбменССайтомПереопределяемый), которая пытается зарегистрировать эти же документы для отправки на сайт. Но на подчиненном узле настройки интеграции с сайтом могут отсутствовать, либо состав плана обмена сайтом урезан.
Чтобы избежать этой коллизии, во всех обработчиках событий, влияющих на регистрацию изменений, необходимо использовать проверку свойства ОбменДанными.Загрузка.
Посмотрим на пример правильной реализации обработчика:
Процедура ПередЗаписьюДокументаПередЗаписью(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
// Если данные загружаются в процессе обмена РИБ, отключаем любые дополнительные регистрации!
Если Источник.ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
// Ниже идет стандартный код регистрации изменений для внешних систем
ПланыОбмена.ЗарегистрироватьИзменения(ПланыОбмена.ОбменССайтом.НайтиПоКоду("SITE"), Источник.Ссылка);
КонецПроцедуры
Этот простой блок кода гарантирует, что при загрузке пакета РИБ система не будет пытаться инициировать побочные процессы регистрации изменений в другие планы обмена, что полностью исключит возникновение ошибки некорректных параметров.
---
Мы проанализировали причины сбоев обмена в распределенных информационных базах 1С. Подводя итоги, отметим, что своевременное проведение профилактического тестирования и исправления баз данных, аккуратное обращение с регламентными операциями закрытия месяца, а также грамотная расстановка проверок ОбменДанными.Загрузка в кодовой базе конфигурации позволяют полностью обезопасить систему от внезапных остановок обмена РИБ.