В практике сопровождения и разработки баз 1С нередко встречается парадоксальная ситуация: в режиме «Конфигуратор» в дереве метаданных определенный реквизит (например, у справочника Номенклатура) отсутствует, однако в режиме «1С:Предприятие» поле по-прежнему отображается на форме, доступно в коде через Объект.ИмяРеквизита, успешно изменяется и сохраняет свои значения. Разберем причины возникновения такой коллизии, возможные риски и пошаговый порядок действий для корректного восстановления структуры метаданных без потери накопленной информации.
Проанализируем основные факторы, которые приводят к подобному поведению системы:
Config, ConfigSave, Params) могут войти в несогласованное состояние. В СУБД физическая колонка таблицы (например, _FldXXXX) остается существующей, серверные процессы 1С продолжают работать со старым кэшем схемы данных, тогда как конфигуратор уже считает реквизит удаленным.snccntx в srvinfo), из-за чего рабочие процессы rphost продолжают отдавать клиентам устаревшую структуру объекта.Если в дереве метаданных конфигуратора просто создать новый реквизит с тем же именем, платформа сгенерирует для него новый уникальный идентификатор (GUID). В таблице СУБД будет выделена новая колонка (например, _FldYYYY), которая не будет связана со старой колонкой (_FldXXXX). При первой же полноценной реструктуризации старая колонка будет удалена СУБД, а новая окажется абсолютно пустой. Это приведет к безвозвратной потере всех исторических значений реквизита.
Прежде чем приступать к исправлению структуры, проверим текущее состояние базы:
ПолучитьСтруктуруХраненияБазыДанных() программно проверим наличие физической колонки в СУБД.Посмотрим на пример кода для проверки структуры хранения в базе данных:
СтруктураБазы = ПолучитьСтруктуруХраненияБазыДанных();
ТаблицаНоменклатуры = СтруктураБазы.Найти("Справочник.Номенклатура", "Имя");
Если ТаблицаНоменклатуры <> Неопределено Тогда
Для Каждого Поле Из ТаблицаНоменклатуры.Поля Цикл
Сообщить("Имя поля: " + Поле.ИмяПоля + " | Имя в СУБД: " + Поле.ИмяТаблицыХранения);
КонецЦикла;
КонецЕсли;
Пока данные реквизита еще читаются в режиме «1С:Предприятие», выполним их экстренную выгрузку во внешний файл или временное хранилище. Это гарантирует сохранность информации при любых дальнейших сбоях.
Рассмотрим пример внешней обработки для выгрузки значений проблемного реквизита в файл JSON:
// Создадим структуру для сохранения соответствия ссылок и значений
МассивДанных = Новый Массив;
Выборка = Справочники.Номенклатура.Выбрать();
Пока Выборка.Следующий() Цикл
ОбъектСсылка = Выборка.Ссылка;
// Проверяем наличие реквизита у объекта
Попытка
ЗначениеРеквизита = Выборка.R1;
Исключение
ЗначениеРеквизита = Неопределено;
КонецПопытки;
Если ЗначениеРеквизита <> Неопределено Тогда
ЭлементСписка = Новый Структура;
ЭлементСписка.Вставить("УИД", Строка(ОбъектСсылка.УникальныйИдентификатор()));
ЭлементСписка.Вставить("Значение", ЗначениеРеквизита);
МассивДанных.Добавить(ЭлементСписка);
КонецЕсли;
КонецЦикла;
// Записываем массив данных в файл формата JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.ОткрытьФайл("C:\temp\backup_R1.json");
ЗаписатьJSON(ЗаписьJSON, МассивДанных);
ЗаписьJSON.Закрыть();
Сообщить("Выгрузка успешно завершена. Сохранено записей: " + МассивДанных.Количество());
Разберем по шагам действия по очистке служебных кэшей для устранения рассинхронизации:
.dt или бэкап средствами СУБД).1C:Enterprise 8.3 Server Agent. В каталоге кластера (srvinfo) удалим временные файлы рабочих процессов и кэша (папки с именами сессий и snccntx).%LocalAppData%\1C\1Cv8 и %AppData%\1C\1Cv8)..cf)..cf. Данная операция принудительно перезаписывает таблицы Config и ConfigSave, устраняя остаточные следы динамических обновлений.Если после синхронизации реквизит окончательно удален из дерева конфигурации и базы данных, восстановим его корректным способом:
R1 в справочник Номенклатура с нужным типом данных.Посмотрим на пример программной загрузки значений реквизита из ранее сохраненного файла JSON:
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.ОткрытьФайл("C:\temp\backup_R1.json");
МассивДанных = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
Для Каждого Элемент Из МассивДанных Цикл
СсылкаНаНоменклатуру = Справочники.Номенклатура.ПолучитьСсылку(Новый УникальныйИдентификатор(Элемент.УИД));
// Проверяем, существует ли элемент в базе
ОбъектНоменклатуры = СсылкаНаНоменклатуру.ПолучитьОбъект();
Если ОбъектНоменклатуры <> Неопределено Тогда
ОбъектНоменклатуры.R1 = Элемент.Значение;
Попытка
// Записываем объект без вызова лишних проверок при необходимости
ОбъектНоменклатуры.Записать();
Исключение
Сообщить("Ошибка при записи элемента: " + СсылкаНаНоменклатуру + " (" + ОписаниеОшибки() + ")");
КонецПопытки;
КонецЕсли;
КонецЦикла;
Сообщить("Загрузка данных реквизита R1 завершена.");
Следуя данному регламенту, мы гарантированно защитим данные от случайного удаления при реструктуризации таблиц СУБД и приведем дерево метаданных конфигурации в полное соответствие с реальной структурой базы данных.