Как исправить ошибку «ХранилищеФайлов. Имеются записи с одинаковыми измерениями» при обновлении 1С?

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

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

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

Почему возникает эта ошибка при реструктуризации

Проанализируем техническую сторону процесса обновления. Регистр сведений ХранилищеФайлов (или аналогичный ему в Библиотеке стандартных подсистем — ДвоичныеДанныеФайлов) предназначен для хранения содержимого присоединенных файлов в базе данных. Ключевым измерением регистра является Файл, имеющее составной тип данных (ссылки на различные справочники присоединенных файлов или определяемый тип ПрисоединенныйФайл).

Коллизия возникает по одной из следующих причин:

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

Шаг 1. Правильный поиск конфликтных записей запросом

Рассмотрим распространенную ошибку при написании запроса для поиска дублей. Если использовать агрегатную функцию КОЛИЧЕСТВО(Поле), платформа 1С автоматически исключит строки со значением NULL из подсчета. В результате запрос покажет, что дублей нет, хотя СУБД видит конфликт.

Чтобы обнаружить все записи, включая пустые и некорректные, используем подсчет всех строк через КОЛИЧЕСТВО(*):


ВЫБРАТЬ
    Регистр.Файл КАК Файл,
    КОЛИЧЕСТВО(*) КАК КоличествоСтрок
ИЗ
    РегистрСведений.ХранилищеФайлов КАК Регистр
СГРУППИРОВАТЬ ПО
    Регистр.Файл
ИМЕЮЩИЕ
    КОЛИЧЕСТВО(*) > 1

Также проверим регистр на наличие строк, где измерение не заполнено или содержит неразрешенные ссылки:


ВЫБРАТЬ
    Регистр.Файл КАК Файл
ИЗ
    РегистрСведений.ХранилищеФайлов КАК Регистр
ГДЕ
    Регистр.Файл ЕСТЬ NULL
    ИЛИ Регистр.Файл.Ссылка ЕСТЬ NULL

Если в результате запроса мы увидели строки со значением NULL или пустые ссылки, именно они блокируют применение изменений конфигурации.

Решение 1. Замещение пустых измерений уникальными ссылками (без потери данных)

Разберем оригинальный и надежный способ устранения дублей, когда требуется сохранить остальные рабочие данные регистра. Поскольку удалить строки с NULL через отбор невозможно, мы можем прочитать все записи регистра в память, найти строки с незаполненным измерением и программно присвоить им ссылки на новые уникальные элементы справочника.

Выполним процедуру по шагам:

  1. Создадим в пользовательском режиме (например, через любой справочник с поддержкой присоединенных файлов — «Физические лица» или «Договоры») столько новых временных файлов, сколько пустых записей показал проверочный запрос.
  2. Получим ссылки на эти созданные файлы во внешней обработке.
  3. Прочитаем весь регистр без установки отборов через объект РегистрСведенийНаборЗаписей, найдем незаполненные строки и перезапишем в них измерение Файл созданными ссылками.

Посмотрим на пример программного кода для реализации этого алгоритма:


// Ссылки на заранее созданные фиктивные файлы
МассивФайлов = Новый Массив;
МассивФайлов.Добавить(ФайлЗаглушка1);
МассивФайлов.Добавить(ФайлЗаглушка2);

НаборЗаписей = РегистрыСведений.ХранилищеФайлов.СоздатьНаборЗаписей();
НаборЗаписей.Прочитать();

Индекс = 0;
Для Каждого Запись Из НаборЗаписей Цикл
    Если НЕ ЗначениеЗаполнено(Запись.Файл) Тогда
        Если Индекс < МассивФайлов.Количество() Тогда
            Запись.Файл = МассивФайлов[Индекс];
            Индекс = Индекс + 1;
        КонецЕсли;
    КонецЕсли;
КонецЦикла;

НаборЗаписей.Записать();

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

Решение 2. Полная очистка с предварительной выгрузкой данных (XDTO)

Если записей с поврежденными ссылками много или предыдущий способ реализовать неудобно, разберем универсальный вариант с временным экспортом бинарных данных через механизм сериализации.

Выполним следующие действия по шагам:

  1. Выгрузка данных. До применения обновления конфигурации выгрузим корректные записи регистра в XML-файл с помощью объекта СериализаторXDTO во внешней обработке:
    
    ЗаписьXML = Новый ЗаписьXML;
    ЗаписьXML.ОткрытьФайл("C:\Temp\ХранилищеФайлов.xml");
    
    Набор = РегистрыСведений.ХранилищеФайлов.СоздатьНаборЗаписей();
    Набор.Прочитать();
    
    СериализаторXDTO.ЗаписатьXML(ЗаписьXML, Набор);
    ЗаписьXML.Закрыть();
    
  2. Очистка таблицы. Полностью очистим регистр сведений перед реструктуризацией. Для этого запишем пустой набор записей без отборов:
    
    Набор = РегистрыСведений.ХранилищеФайлов.СоздатьНаборЗаписей();
    Набор.Записать();
    
  3. Применение обновления. Запустим обновление конфигурации базы данных в конфигураторе. Пустая таблица реструктуризируется мгновенно и без конфликтов индексов.
  4. Обратная загрузка. Загрузим записи обратно из сохраненного XML-файла, пропуская поврежденные и пустые элементы, чтобы не воссоздавать ошибку:
    
    ЧтениеXML = Новый ЧтениеXML;
    ЧтениеXML.ОткрытьФайл("C:\Temp\ХранилищеФайлов.xml");
    
    НаборЗагрузки = СериализаторXDTO.ПрочитатьXML(ЧтениеXML);
    ЧтениеXML.Закрыть();
    
    // Оставляем только строки с заполненным измерением
    ИндексСтроки = НаборЗагрузки.Количество() - 1;
    Пока ИндексСтроки >= 0 Цикл
        ТекущаяЗапись = НаборЗагрузки[ИндексСтроки];
        Если НЕ ЗначениеЗаполнено(ТекущаяЗапись.Файл) Тогда
            НаборЗагрузки.Удалить(ИндексСтроки);
        КонецЕсли;
        ИндексСтроки = ИндексСтроки - 1;
    КонецЦикла;
    
    НаборЗагрузки.Записать();
    

Решение 3. Восстановление физической и логической целостности базы данных

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

  1. Создадим полную резервную копию базы данных (файл выгрузки .dt или прямое копирование файла 1Cv8.1CD при выключенных процессах платформы).
  2. Запустим утилиту chdbfl.exe, которая находится в каталоге установки платформы (папка bin), и выполним проверку с включенной опцией «Исправлять обнаруженные ошибки».
  3. Откроем базу в режиме «Конфигуратор» и запустим процедуру «Тестирование и исправление» (меню Администрирование — Тестирование и исправление...).
  4. В списке проверок выберем:
    • «Проверка логической целостности»;
    • «Проверка ссылочной целостности».
  5. В блоке параметров «При наличии ссылок на несуществующие объекты» установим переключатель в положение «Очищать ссылки» или «Удалять записи».

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

← На главную