Нарушение ссылочной целостности в базах данных «1С:Предприятие» — одна из наиболее неприятных технических проблем. В интерфейсе пользователя это выглядит как появление надписи «<Объект не найден>» с длинным буквенно-цифровым идентификатором в полях документов, отчетов или справочников. Подобная ситуация чаще всего происходит из-за аварийного завершения работы сервера, скачков напряжения (в файловых базах), некорректно настроенной синхронизации или грубых ручных манипуляций в обход бизнес-логики системы.
В этой статье мы подробно разберем, как восстановить утерянные объекты (например, контрагентов, номенклатуру или документы) и вернуть им их оригинальный уникальный идентификатор (GUID). Это позволит автоматически «склеить» битые ссылки во всех исторических документах без необходимости открывать прошлые периоды, перепроводить документы и нарушать последовательность партионного или бухгалтерского учета.
Каждая запись в базе данных 1С идентифицируется глобальным уникальным идентификатором — UUID (Universal Unique Identifier). Когда один объект (например, документ «Платежное поручение») ссылается на другой (справочник «Контрагенты»), в таблице платежного поручения физически записывается этот 16-байтный UUID контрагента.
Если сам контрагент по какой-то причине удаляется или повреждается на уровне СУБД, физическая ссылка в документе остается «висеть» в пустоту. При попытке прочитать данные по этой ссылке платформа 1С понимает, что записи с таким UUID в целевой таблице справочника больше нет, и выводит строковую заглушку вида <Объект не найден> (84:bf5600145e3710ab11dda4c605dbe824).
Многие специалисты сразу запускают штатный механизм «Тестирование и исправление» (ТиИ) в Конфигураторе, выбирая опцию «Создавать объекты» при наличии ссылок на несуществующие элементы. Однако на практике этот метод часто дает сбой или не срабатывает. Выделим три основные причины такого поведения:
Проанализируем пошагово комплексную методику восстановления данных — от диагностики физической целостности до программного восстановления объектов по их оригинальным GUID.
Если вы столкнулись со сбоем питания или внезапным выключением компьютера, на котором установлена файловая база данных 1С, перед запуском любых процедур в Конфигураторе необходимо убедиться в физической целостности файла базы данных 1Cv8.1CD. Логическое восстановление поверх физически битых таблиц может безвозвратно уничтожить уцелевшие данные.
Выполним физическую проверку с помощью специализированной утилиты, поставляемой вместе с платформой 1С:
1Cv8.1CD простым копированием в безопасное место.C:\Program Files\1cv8\[Номер_версии_платформы]\bin\.chdbfl.exe.1Cv8.1CD.Утилита проверит физическую структуру таблиц, заголовки страниц, соответствие индексов и восстановит поврежденную разметку файла. Только после успешного завершения работы chdbfl.exe можно переходить к работе в Конфигураторе или написанию скриптов.
Если база данных прошла физическую проверку, попробуем запустить логическое восстановление ссылочной целостности штатными средствами платформы. Нам необходимо принудительно заставить 1С создать пустые элементы-заглушки для всех потерянных объектов.
Рассмотрим порядок действий:
Если логическая структура не нарушена критически, система создаст в соответствующих справочниках (например, в справочнике «Контрагенты») новые элементы с наименованием «Объект не найден...». Эти элементы получат те самые оригинальные UUID, которые требуются закрытым документам. Вам останется лишь зайти в эти элементы и вручную переписать их правильные названия, ИНН и другие реквизиты, взяв данные из архивной копии базы данных.
Что делать, если тестирование и исправление не помогло или вы не хотите запускать длительный процесс ТиИ на огромной базе данных ради нескольких поврежденных контрагентов? Мы можем воссоздать их программно. Для этого нам понадобится написать небольшую внешнюю обработку. Для этой задачи можно использовать инструмент для поиска битых ссылок и автоматического создания объектов.
Сначала разберем способ воссоздания объекта, если у нас есть только текстовое представление битой ссылки из интерфейса 1С. Например, программа выдает ошибку: <Объект не найден> (84:bf5600145e3710ab11dda4c605dbe824).
Текст в скобках состоит из двух частей, разделенных двоеточием:
84 — это внутренний шестнадцатеричный код типа метаданных (номера таблицы в базе данных).bf5600145e3710ab11dda4c605dbe824 — это шестнадцатеричная запись уникального идентификатора (GUID), но записанная во внутреннем («перевернутом») формате хранения СУБД.Чтобы превратить внутреннее представление в стандартный UUID формата 8-4-4-4-12, нам нужно программно переставить блоки символов местами по следующей схеме:
Функция ПолучитьСтандартныйGUID(ВнутреннийКод) Экспорт
// ВнутреннийКод = "bf5600145e3710ab11dda4c605dbe824"
Блок1 = Сред(ВнутреннийКод, 25, 8); // "05dbe824"
Блок2 = Сред(ВнутреннийКод, 21, 4); // "a4c6"
Блок3 = Сред(ВнутреннийКод, 17, 4); // "11dd"
Блок4 = Сред(ВнутреннийКод, 1, 4); // "bf56"
Блок5 = Сред(ВнутреннийКод, 5, 12); // "00145e3710ab"
РезультатGUID = Блок1 + "-" + Блок2 + "-" + Блок3 + "-" + Блок4 + "-" + Блок5;
Возврат Новый УникальныйИдентификатор(РезультатGUID);
КонецФункции
После того как мы получили стандартный UUID, мы можем сгенерировать ссылку нужного типа и записать новый элемент справочника с этим идентификатором с помощью метода УстановитьСсылкуНового(). Посмотрим на пример кода:
Процедура ВосстановитьКонтрагентаПоВнутреннейСтроке(СтрокаКода)
// СтрокаКода — это "bf5600145e3710ab11dda4c605dbe824"
ПотребныйGUID = ПолучитьСтандартныйGUID(СтрокаКода);
// Получаем пустую ссылку с нужным нам GUID
СсылкаНового = Справочники.Контрагенты.ПолучитьСсылку(ПотребныйGUID);
// Создаем новый элемент справочника
НовыйКонтрагент = Справочники.Контрагенты.СоздатьЭлемент();
// Привязываем элемент к созданной ссылке
НовыйКонтрагент.УстановитьСсылкуНового(СсылкаНового);
// Заполняем реквизиты данными (можно взять их из архивной базы)
НовыйКонтрагент.Наименование = "Восстановленный контрагент (ООО Вектор)";
НовыйКонтрагент.ИНН = "7701020304";
НовыйКонтрагент.КПП = "770101001";
Попытка
НовыйКонтрагент.Записать();
Сообщить("Объект успешно восстановлен с исходным GUID!");
Исключение
Сообщить("Ошибка при записи объекта: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Как только этот код выполнится, битые ссылки в закрытых периодах во всех документах автоматически начнут отображать вновь созданного контрагента. Никакие движения документов при этом не изменятся, и перепроведение прошлых периодов не потребуется.
Если у нас есть архивная копия базы данных, в которой поврежденные контрагенты еще целы, мы можем перенести их GUID в рабочую базу гораздо проще — используя механизм внутренней сериализации платформы 1С.
Выясним алгоритм действий по шагам:
// Предположим, ВыбралиКонтрагента — это ссылка на нужного контрагента в бэкапе
СтрокаВнутр = ЗначениеВСтрокуВнутр(ВыбралиКонтрагента);
// Строка будет выглядеть примерно так: {"#",54c3544f-...,9659:ab2b...}
Сообщить(СтрокаВнутр);
Процедура ВосстановитьИзВнутреннейСтроки()
ВнутренняяСтрокаИзБэкапа = "{""#"",54c3544f-...,9659:ab2b...}"; // Вставьте сюда скопированную строку
// Восстанавливаем ссылку в рабочей базе.
// Платформа создаст объект-ссылку нужного типа с правильным GUID,
// даже если самого элемента в базе еще нет физически.
СсылкаНаОбъект = ЗначениеИзСтрокиВнутр(ВнутренняяСтрокаИзБэкапа);
// Проверим, действительно ли объекта нет в базе
Если СсылкаНаОбъект.ПолучитьОбъект() = Неопределено Тогда
НовыйЭлемент = Справочники.Контрагенты.СоздатьЭлемент();
НовыйЭлемент.УстановитьСсылкуНового(СсылкаНаОбъект);
// Заполняем реквизиты значениями из бэкапа
НовыйЭлемент.Наименование = "ООО Ромашка (Восстановлен)";
НовыйЭлемент.Записать();
Сообщить("Элемент успешно воссоздан по данным бэкапа!");
Иначе
Сообщить("Элемент уже существует в этой базе данных!");
EndIf;
КонецПроцедуры
Этот способ является наиболее безопасным и быстрым, так как исключает человеческий фактор при ручном перевороте байтов в строке UUID.
В случае работы базы данных под управлением MS SQL Server или PostgreSQL администраторы баз данных могут произвести восстановление непосредственно через SQL-запросы. Данный метод требует высокой квалификации и полного понимания структуры таблиц 1С.
Рассмотрим структуру ссылки: <Объект не найден> (9659:ab2b001b78e134e011dfec0814418025).
9659 соответствует идентификатору таблицы в СУБД. Чтобы узнать точное физическое имя таблицы, можно воспользоваться функцией платформы ПолучитьСтруктуруХраненияБазыДанных(). Для справочника контрагентов имя таблицы на уровне SQL будет иметь вид, например, _Reference9659.ab2b001b78e134e011dfec0814418025 — это шестнадцатеричное значение бинарного поля идентификатора _IDRRef.Для восстановления записи администратор БД может выполнить прямую вставку пустой строки в таблицу СУБД. Пример SQL-запроса для MS SQL Server:
INSERT INTO _Reference9659 (_IDRRef, _Version, _Marked, _IsFolder, _Description)
VALUES (0xab2b001b78e134e011dfec0814418025, 1, 0x00, 0x00, 'Восстановлен через SQL')
Важное предупреждение: Использование прямых SQL-запросов INSERT в таблицы данных 1С нарушает лицензионное соглашение и может привести к рассогласованию индексов полнотекстового поиска и объектного кэша сервера приложений. Используйте этот метод только в крайних случаях и обязательно выполняйте последующую очистку серверного кэша и переиндексацию таблиц.
Простое создание карточки контрагента по его старому UUID решает только визуальную проблему битых ссылок в реквизитах документов. Однако при сильных сбоях питания повреждаются не только таблицы справочников, но и таблицы регистров накопления и сведений (например, регистры «Взаиморасчеты», «НДС», «Контактная информация»). Для их проверки и исправления можно использовать обработку для поиска и восстановления битых ссылок в регистрах.
Рекомендуем выполнить следующие действия после восстановления объектов: