В процессе эксплуатации высоконагруженных систем на базе 1С:Предприятие 8.3 (таких как ERP, КА или БП 3.0) администраторы часто сталкиваются с парадоксальной ситуацией. Утилита Тестирование и исправление (ТиИ) при проверке логической целостности выдает ошибки о наличии записей с битыми ссылками (Объект не найден) в регистре сведений ДанныеПервичныхДокументов. Однако при попытке найти эти записи через консоль запросов, стандартные списки или специализированные обработки очистки, система сообщает, что записей нет. Разберемся детально, почему возникают такие «фантомы», как они влияют на обслуживание базы данных (например, на операцию Shrink в SQL) и как их окончательно вычистить.
Для начала проанализируем роль данного регистра. ДанныеПервичныхДокументов — это системный вспомогательный регистр, предназначенный для хранения агрегированных сведений о документах (номер, дата, организация, тип). Он используется платформой для оптимизации динамических списков, чтобы не выполнять тяжелые соединения (JOIN) со множеством таблиц различных видов документов одновременно.
Записи в этот регистр обычно вносятся автоматически при проведении или записи документов через подписки на события. Основная проблема заключается в том, что при «жестком» удалении документов (например, программным кодом без использования метода Удалить() с контролем ссылочной целостности или сторонними обработками) связанные записи в этом регистре могут остаться «сиротами». Они продолжают физически существовать в таблице SQL, но становятся невидимыми для большинства инструментов 1С.
Существует несколько технических причин, по которым записи, видимые для ТиИ, скрываются от глаз программиста в обычном режиме:
ОбластьДанныхОсновныеДанные. Если в конфигурации включено разделение данных, записи, у которых этот реквизит заполнен некорректно или равен 0 (при активном сеансе в конкретной области), будут отсекаться механизмом RLS или встроенными фильтрами области данных.Поскольку база данных работает под управлением SQL Server, мы можем проанализировать проблему «изнутри». ТиИ сообщает конкретный идентификатор (GUID), например: 904:81452c4d54cff76711e91d2753434d2b. Это шестнадцатеричное представление ссылки, которая застряла в таблице регистра.
Чтобы найти эту запись в СУБД, выполним следующие шаги:
1. Сначала выясним имя таблицы регистра в SQL. Это можно сделать с помощью функции 1С:
ИмяТаблицы = ПолучитьСтруктуруХраненияБазыДанных().Найти("ДанныеПервичныхДокументов", "Имя").ИмяТаблицыХранения;
Сообщить(ИмяТаблицы); // Например, это будет _InfoReg12345
2. Проанализируем структуру полей. Поля измерений будут называться _FldXXXXRRef (для ссылок) или _FldXXXX_TYPE (для составных типов). Поле разделителя данных обычно называется _DataAreaMainData.
3. Выполним прямой SQL-запрос для поиска записи по GUID, который указало ТиИ. Важно помнить, что в SQL GUID хранится в бинарном виде, и его нужно перевернуть согласно логике хранения 1С (либо искать по окончанию строки):
SELECT * FROM _InfoReg12345
WHERE _FldXXXX_IDRRef = 0x81452C4D54CFF76711E91D2753434D2B
Если запрос возвращает строки, значит, записи физически занимают место в таблице и индексах, что мешает сжатию (Shrink) и дефрагментации базы.
Проанализируем поведение ТиИ. Часто пользователь выбирает режим «Очищать ссылки» или «Удалять объекты», но ошибки не исчезают. Это происходит потому, что в регистре сведений измерение не может быть пустым (NULL или пустая ссылка), если это не разрешено метаданными.
Если ТиИ пытается «очистить» ссылку в измерении, это может привести к нарушению уникальности записей (если уже есть запись с пустой ссылкой) или к ошибке записи объекта. Кроме того, если включено разделение данных, ТиИ, запущенное в контексте всей базы (без разделителей), может не иметь прав на модификацию данных внутри областей, если механизмы защиты платформы блокируют такие изменения.
Попробуем удалить записи через объектную модель НаборЗаписей, принудительно отключив фильтры, насколько это возможно. Рассмотрим пример кода, который обходит записи и пытается их удалить:
// Создаем набор записей
Набор = РегистрыСведений.ДанныеПервичныхДокументов.СоздатьНаборЗаписей();
// Если мы знаем, по какому документу «битая» ссылка, можно попробовать установить отбор.
// Но так как ссылка битая, стандартный отбор через Объект может не сработать.
// В таких случаях лучше использовать запрос к таблице регистра напрямую через МенеджерЗаписей.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Данные.Документ КАК Документ,
| Данные.Организация КАК Организация
|ИЗ
| РегистрСведений.ДанныеПервичныхДокументов КАК Данные
|ГДЕ
| Данные.Документ.Ссылка ЕСТЬ NULL"; // Попытка найти битые ссылки
Результат = Запрос.Выполнить().Выбрать();
Пока Результат.Следующий() Цикл
Менеджер = РегистрыСведений.ДанныеПервичныхДокументов.СоздатьМенеджерЗаписей();
ЗаполнитьЗначенияСвойств(Менеджер, Результат);
Менеджер.Прочитать();
Если Менеджер.Выбран() Тогда
Менеджер.Удалить();
Сообщить("Запись удалена успешно");
КонецЕсли;
КонецЦикла;
Если программные методы 1С и стандартное ТиИ не помогают, а количество записей исчисляется сотнями тысяч (как в рассматриваемом случае — 600 000 записей), наиболее эффективным и безопасным (при наличии бэкапа!) будет прямое удаление через SQL Management Studio.
Внимание: Любые действия с таблицами SQL напрямую должны производиться только при полной уверенности в своих действиях и наличии актуальной резервной копии.
Рассмотрим алгоритм действий в СУБД:
ДанныеПервичныхДокументов, где измерение Документ имеет составной тип, проверка усложняется наличием поля _TYPE.
-- Пример удаления конкретной проблемной записи
DELETE FROM _InfoReg12345
WHERE _FldXXXX_IDRRef = 0x81452C4D54CFF76711E91D2753434D2B;
После удаления на уровне SQL необходимо обязательно выполнить Тестирование и исправление с включенной опцией «Пересчет итогов», чтобы платформа обновила внутренние кэши и агрегаты.
Выясним причину, почему пользователь так стремится удалить эти записи для выполнения операции Shrink. Битые записи в индексах создают логическую несогласованность. Когда SQL Server пытается переместить страницы данных для сжатия файла БД, наличие некорректных указателей в индексах 1С (которые построены по этим измерениям) может приводить к избыточной нагрузке на дисковую подсистему и невозможности эффективно освободить место. Очистка 600 000 «фантомных» строк позволит значительно сократить размер индексов этого регистра и ускорить работу системы в целом.
Проанализировав ситуацию, мы пришли к выводу, что проблема «невидимых» записей в регистре ДанныеПервичныхДокументов является следствием некорректного удаления ведущих объектов и специфики работы платформы с разделителями данных. Для решения рекомендуется:
Помните, что чистота системных регистров — залог стабильной работы механизмов платформы 1С и высокой скорости формирования отчетов.