Переход с файлового варианта базы данных на клиент-серверный (например, можно автоматизировать установку PostgreSQL на Astra Linux) — это стандартный этап масштабирования системы 1С. Однако при достижении базой внушительных размеров (в нашем случае около 20 ГБ) пользователи часто сталкиваются с критическими ошибками. Одной из наиболее сложных проблем является наличие дублирующихся ключей в уникальных индексах и превышение максимально допустимого размера внутреннего файла СУБД 1С. Разберем детально, почему возникают эти ошибки и как их исправить, когда стандартные средства вроде chdbfl.exe не дают результата.
Прежде всего, проанализируем природу ошибки «Превышен максимально допустимый размер внутреннего файла». Файловая база 1С (файл 1Cv8.1CD) имеет внутреннюю структуру, состоящую из множества таблиц. Для каждой такой таблицы (или её индекса) установлено жесткое ограничение — размер не может превышать 4 ГБ. Даже если суммарно база весит 20 ГБ или 100 ГБ, она будет работать до тех пор, пока любая из её внутренних таблиц не «упрется» в этот лимит.
Дубликаты в уникальных индексах часто являются следствием этого ограничения или внезапных сбоев (например, аварийного завершения работы при записи тяжелого документа). Когда таблица достигает критического размера, индекс может перестать корректно обновляться, в то время как сами данные продолжают записываться. В итоге возникают ситуации, когда в таблице существуют две идентичные записи, что недопустимо для уникального индекса СУБД (включая PostgreSQL). Именно поэтому попытка загрузки .dt файла на SQL сервер заканчивается ошибкой: SQL-сервер, в отличие от файлового движка, строго проверяет уникальность при создании индексов.
Выясним, какая именно таблица вызывает сбой. Стандартное тестирование может длиться сутками, поэтому воспользуемся программными методами или обработкой для получения структуры хранения. Выполним в консоли кода или во внешней обработке следующий фрагмент, чтобы получить структуру хранения и сопоставить имена таблиц в файле с объектами метаданных:
СтруктураХранения = ПолучитьСтруктуруХраненияБазыДанных();
Для Каждого Таблица Из СтруктураХранения Цикл
Если Таблица.ИмяТаблицыХранения = "ИМЯ_БИТОЙ_ТАБЛИЦЫ" Тогда // Имя берется из ошибки или ТЖ
Сообщить("Проблема в объекте: " + Таблица.ИмяТаблицы);
КонецЕсли;
КонецЦикла;
Если имя таблицы неизвестно, можно проанализировать работу системы и настроить Технологический журнал. Создадим файл logcfg.xml, который будет отслеживать события EXCP (исключения) и DBV8DBDirect. Это позволит увидеть конкретное имя таблицы (например, _InfoReg12345), на которой прерывается процесс реиндексации или выгрузки данных.
Рассмотрим ситуацию, когда конфигуратор не может завершить тестирование. Попробуем воспользоваться стандартной или адаптивной модификацией обработки «Выгрузка и загрузка данных XML». Разберем этот метод по шагам:
Чаще всего «раздуваются» таблицы итогов регистров накопления или регистры сведений, хранящие историю электронных документов (ЭСФ, ЭДО), как в рассматриваемом случае с документами ЭСФ.
Если выяснилось, что проблемная таблица относится к регистру накопления или бухгалтерии, проанализируем состояние итогов. Дубликаты в индексах итогов можно устранить их полным пересчетом. Выполним следующие действия в Конфигураторе:
Этот процесс физически удаляет старые таблицы итогов и создает их заново, что гарантированно очищает их от фантомных дублей и уменьшает размер файла .1CD.
Для регистров сведений, где часто возникают дубли в уникальных ключах, стандартные методы правки данных могут не сработать. В этом случае напишем небольшую процедуру, которая «перезапишет» данные, игнорируя дубли при чтении. Рассмотрим пример кода:
Менеджер = РегистрыСведений.ИмяВашегоРегистра;
Набор = Менеджер.СоздатьНаборЗаписей();
// Если мы знаем проблемный период или измерения:
// Набор.Отбор.Период.Установить(ДатаНачала, ДатаКонца);
Набор.Прочитать();
ТаблицаДанных = Набор.Выгрузить();
// Удаляем дубли в таблице значений программно
ТаблицаДанных.Свернуть("Период, Измерение1, Измерение2", "Ресурс1");
Набор.Загрузить(ТаблицаДанных);
Набор.ОбменДанными.Загрузка = Истина;
Попытка
Набор.Записать();
Исключение
Сообщить("Ошибка при записи: " + ОписаниеОшибки());
КонецПопытки;
Использование свойства ОбменДанными.Загрузка = Истина критически важно: это заставляет платформу минимизировать проверки, что позволяет перезаписать «битый» набор записей.
Проанализируем ситуацию: если база весит 20 ГБ и содержит логические ошибки, создание .dt и его загрузка в SQL могут постоянно давать сбой. В таких случаях рекомендуем использовать механизм Универсального обмена данными.
V8Exchan83.epf.Преимущество этого метода в том, что данные переносятся на уровне объектов метаданных. При записи в SQL-базу платформа 1С автоматически сформирует новые, чистые индексы, а дублирующиеся записи либо будут схлопнуты, либо вызовут ошибку на конкретном объекте, который можно будет исправить индивидуально.
Иногда ошибка дублей бывает вызвана некорректным состоянием локального кеша. Перед проведением любых работ по миграции обязательно очистим временные файлы. Рассмотрим, где они находятся:
Нужно удалить содержимое папок %AppData%\1C\1Cv8\ и %LocalAppData%\1C\1Cv8\. Также стоит запустить Тестирование и исправление только с одной выбранной опцией — «Сжатие таблиц информационной базы». Это пересоберет физический файл 1Cv8.1CD и может высвободить место, если таблица была раздута из-за большого количества удаленных записей, которые физически еще занимают место в страницах файла.
Таким образом, комбинируя методы программной очистки регистров, пересчета итогов и альтернативной выгрузки данных, мы сможем успешно преодолеть барьер в 4 ГБ и перевести тяжелую базу на SQL без потери важной информации.