Как найти и удалить дубли в регистре Версии объектов при обновлении 1С

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

При обновлении крупных конфигураций, таких как 1С:Комплексная автоматизация 2 или 1С:ERP, администраторы и программисты часто сталкиваются с ошибками реструктуризации базы данных. Одной из самых неприятных является ошибка, связанная с регистром сведений ВерсииОбъектов. Система сообщает о наличии дублирующихся записей, что не позволяет завершить переход на новый релиз. Ситуация осложняется тем, что стандартные запросы часто не показывают видимых дублей.

В этой статье мы подробно разберем, почему возникают «невидимые» дубли, как их диагностировать и какими способами можно очистить регистр, чтобы успешно продолжить обновление. Чтобы автоматизировать обслуживание и проверку системы при переходе на новые релизы, можно использовать автоматическое обновление и архивирование баз 1С.

Выясняем причину возникновения ошибок

Регистр сведений ВерсииОбъектов является независимым и непериодическим. Его уникальность определяется измерениями Объект и НомерВерсии. Казалось бы, появление дублей в такой структуре невозможно на логическом уровне 1С, однако на практике это происходит по нескольким причинам:

  1. Битые ссылки в измерениях: В поле Объект могут находиться записи со значением «Объект не найден». Если таких записей несколько с одинаковыми номерами версий, при реструктуризации СУБД (например, MS SQL Server) не может создать уникальный индекс.
  2. Логические ошибки механизмов БСП: Иногда из-за сбоев в работе фоновых заданий или при программной записи данных механизмом версионирования в регистр попадают некорректные данные.
  3. Физическое повреждение индексов: На уровне SQL-таблицы данные могут быть задублированы, хотя сама платформа 1С при попытке чтения выдает только одну запись или вовсе пустой результат.
  4. Переход между версиями (2.4 -> 2.5): При масштабных обновлениях меняется структура хранения данных, и старые записи (особенно созданные много лет назад в очень ранних релизах) могут конфликтовать с новыми правилами типизации полей.

Шаг 1: Диагностика «невидимых» дублей запросом

Если стандартный запрос по группировке не дает результатов, проанализируем ситуацию глубже. Попробуем найти записи, где объект не определен или ссылается на удаленный элемент (битая ссылка). Рассмотрим следующий запрос:


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

Если этот запрос пуст, проанализируем наличие записей с «битыми» ссылками. Выясним причину через проверку типа объекта:


ВЫБРАТЬ
    ВерсииОбъектов.Объект,
    ВерсииОбъектов.НомерВерсии
ИЗ
    РегистрСведений.ВерсииОбъектов КАК ВерсииОбъектов
ГДЕ
    ВерсииОбъектов.Объект.Ссылка ЕСТЬ NULL
    И ВерсииОбъектов.Объект <> ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка) // Проверьте основные типы

Важный момент: Если в технологическом журнале (ТЖ) зафиксирована ошибка Primary Key Violation, там часто указан конкретный идентификатор (GUID). Попробуйте найти запись в базе именно по этому GUID, используя консоль запросов.

Шаг 2: Использование типового механизма очистки (БСП)

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

Разберем, как это настроить:

  1. Перейдем в раздел Администрирование — Общие настройки — История изменений.
  2. Настроим срок хранения версий (например, установим «За последнюю неделю» или «За последний месяц»).
  3. Запустим регламентное задание Очистка устаревших версий объектов.

Если нам нужно запустить очистку программно и принудительно, мы можем использовать метод программного интерфейса:


// Вызов в контексте серверного модуля или внешней обработки
ВерсионированиеОбъектов.ОчиститьУстаревшиеВерсииОбъектов();

Этот метод хорош тем, что он удаляет данные порциями, не вызывая переполнения лога транзакций и не блокируя таблицу на длительное время. Для решения этой задачи также подойдёт обработка для удаления устаревших версий объектов в КА и ERP.

Шаг 3: Программное удаление «бесполезных» версий

Часто база «пухнет» из-за того, что пользователи нажимают «Провести и закрыть» в документах, не внося никаких изменений. В регистре создаются идентичные копии данных. Разберем алгоритм, как найти и «почикать» такие дубли по содержанию:

  1. Выбираем все версии для конкретного объекта, отсортированные по номеру.
  2. Для каждой версии извлекаем ХранилищеЗначения из ресурса ВерсияОбъекта.
  3. Сравниваем двоичные данные текущей версии с предыдущей (например, через вычисление хеш-суммы MD5).
  4. Если данные идентичны — удаляем текущую запись регистра.

Посмотрим на пример кода для удаления дублей содержания:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	ВерсииОбъектов.Объект КАК Объект,
    |	ВерсииОбъектов.НомерВерсии КАК НомерВерсии
    |ИЗ
    |	РегистрСведений.ВерсииОбъектов КАК ВерсииОбъектов
    |УПОРЯДОЧИТЬ ПО
    |	Объект,
    |	НомерВерсии";

Выборка = Запрос.Выполнить().Выбрать();
ТекущийОбъект = Неопределено;
ПредыдущийХеш = "";

Пока Выборка.Следующий() Цикл
    Если ТекущийОбъект <> Выборка.Объект Тогда
        ТекущийОбъект = Выборка.Объект;
        ПредыдущийХеш = "";
    КонецЕсли;

    // Здесь должна быть логика извлечения данных из ХранилищаЗначения
    // и сравнение Хеша. Если Хеш совпал с ПредыдущийХеш:
    // Набор = РегистрыСведений.ВерсииОбъектов.СоздатьНаборЗаписей();
    // Набор.Отбор.Объект.Установить(Выборка.Объект);
    // Набор.Отбор.НомерВерсии.Установить(Выборка.НомерВерсии);
    // Набор.Записать(); 
КонецЦикла;

Шаг 4: Радикальное решение перед обновлением

Если регистр содержит миллионы записей (например, 25 000 000+), а обновление критично запустить «вчера», самым эффективным способом будет полная очистка регистра. Помните, что при этом вся история изменений объектов будет удалена, но сами объекты останутся нетронутыми. Для планового сокращения объема исторических данных в крупных информационных системах применяется многопоточная свёртка 1С:ERP.

Проанализируем способы быстрой очистки:

Способ А: Программный (через 1С)

Если база работает в файловом режиме или вы не имеете доступа к SQL-консоли, используйте пустой набор записей:


Набор = РегистрыСведений.ВерсииОбъектов.СоздатьНаборЗаписей();
// Отбор не устанавливаем, чтобы очистить весь регистр
Набор.Записать();

Способ Б: Через SQL (для клиент-серверного варианта)

Это самый быстрый способ. Выясним имя таблицы в СУБД (через функцию ПолучитьСтруктуруХраненияБазыДанных) и выполним команду TRUNCATE TABLE. Это мгновенно освободит место и удалит все записи без записи каждой операции в лог транзакций.

Важно: После выполнения TRUNCATE на уровне SQL обязательно выполните Тестирование и исправление (ТИИ) в конфигураторе 1С (пункты «Реиндексация таблиц» и «Проверка логической целостности»), чтобы платформа корректно восприняла изменения в физической структуре.

Резюме

Мы рассмотрели различные подходы к решению проблемы с дублями в регистре версий. Если ваша задача — просто «проскочить» обновление, наиболее разумным будет полная или частичная очистка регистра за старые периоды. Если же история версий жизненно необходима, сфокусируйтесь на поиске битых ссылок и проверке физической целостности БД через SQL-запросы или технологический журнал.

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

← На главную