Как исправить ошибки дублирования объектов при восстановлении базы 1С в PostgreSQL из SQL-дампа?

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

Разберем распространенную проблему, с которой сталкиваются администраторы при развертывании копии рабочей базы 1С на сервере PostgreSQL. При накате текстового дампа (сгенерированного через pg_dump) на новую чистую базу процесс завершается множеством критических ошибок. В консоль выводятся сообщения о том, что функции, индексы или системные таблицы уже существуют.

Типичный лог таких ошибок выглядит следующим образом:


psql:/var/archive/db_backup.sql:180: ОШИБКА:  функция "datediff2" с аргументами таких типов уже существует
psql:/var/archive/db_backup.sql:10042906: ОШИБКА:  создать уникальный индекс "paramsng_pkey" не удалось
DETAIL:  Ключ (filename, partno)=(ibparams.inf, 0) дублируется.
psql:/var/archive/db_backup.sql:10277953: ОШИБКА:  отношение "byname" уже существует
psql:/var/archive/db_backup.sql:10277960: ОШИБКА:  отношение "byname_v8userpwdplcs" уже существует

Выясним причину такого поведения СУБД и платформы, а затем рассмотрим подробный и безопасный алгоритм создания копии базы.

Почему возникают ошибки дублирования объектов

Появление этих ошибок почти всегда вызвано одной из двух причин:

  1. Преждевременная регистрация базы в кластере 1С:Предприятия. Это главная причина. Если перед восстановлением дампа информационная база уже была добавлена в консоли администрирования кластера 1С (или в ней указано имя создаваемой базы СУБД), процесс rphost немедленно подключается к PostgreSQL. Обнаружив пустую или частично заполненную базу, платформа 1С автоматически инициализирует служебную структуру: создает служебные функции (включая datediff2), таблицы конфигурации (paramsng), таблицы пользователей (v8users) и первичные индексы. Когда утилита psql параллельно доходит до команд создания этих же объектов из дампа, СУБД выдает ошибки о нарушении уникальности ключей и невозможности повторного создания таблиц.
  2. Загрязнение системного шаблона СУБД. По умолчанию команда CREATE DATABASE копирует данные из системного шаблона template1. Если в эту шаблонную базу ранее по ошибке вносились изменения или накатывались расширения, все эти объекты автоматически копируются в любую вновь созданную базу данных, создавая коллизии при импорте бэкапа.

Пошаговый регламент правильного восстановления базы

Чтобы избежать блокировок и конфликтов структуры, разберем по шагам правильную последовательность действий.

Шаг 1. Полная очистка поврежденной базы

Если процесс восстановления уже упал с ошибками, продолжать работу в этой же базе нельзя: в ней нарушена логическая целостность данных. Базу данных необходимо полностью пересоздать. Сначала сбросим все активные сеансы (включая возможные попытки подключения кластера 1С) и удалим базу:


SELECT pg_terminate_backend(pid) 
FROM pg_stat_activity 
WHERE datname = 'db_copy' AND pid <> pg_backend_pid();

DROP DATABASE db_copy;

Шаг 2. Создание чистой базы без использования template1

Создадим новую базу данных, явно указав в качестве шаблона полностью пустой системный шаблон template0. Это гарантирует отсутствие любых посторонних объектов:

CREATE DATABASE db_copy WITH TEMPLATE template0 ENCODING 'UTF8';

Важно: на этом шаге категорически запрещено добавлять информационную базу в кластер серверов 1С. Связь между 1С и СУБД должна отсутствовать вплоть до полного завершения восстановления.

Шаг 3. Накат резервной копии

Запустим восстановление данных из резервной копии средствами PostgreSQL. Если используется текстовый дамп, передадим утилите psql флаг немедленной остановки при первой же ошибке, чтобы исключить скрытую порчу данных:

psql -U postgres -v ON_ERROR_STOP=1 -d db_copy -f /var/archive/db_backup.sql

Дожидаемся корректного завершения процесса без ошибок.

Шаг 4. Подключение базы данных к кластеру 1С

Только после того как утилита восстановления полностью отработала, переходим в консоль администрирования серверов 1С:Предприятия и регистрируем новую информационную базу.

  1. Указываем рабочее имя информационной базы и параметры подключения к СУБД (имя сервера, имя только что созданной базы db_copy, пользователя и пароль).
  2. Обязательно снимаем флаг «Создать базу данных в случае её отсутствия». База уже существует и наполнена данными.
  3. Обязательно устанавливаем флаги:
    • «Блокировка регламентных заданий включена»;
    • «Блокировка начала сеансов включена».
    Это критически необходимо, чтобы восстанавливаемая копия базы не начала автоматически выполнять боевые задачи: рассылать письма клиентам, подключаться к банковским шлюзам или запускать регламентные обмены с внешними системами.

Оптимизация резервного копирования: переход с текстового SQL на Custom/Directory формат

Проанализируем используемый подход к созданию бэкапов. Выгрузка в текстовый SQL-файл (pg_dump | pigz > backup.sql.gz) имеет существенные недостатки для баз 1С:

  1. Восстановление через psql работает строго в один поток, что для баз объемом в сотни гигабайт занимает много часов.
  2. Текстовые скрипты чувствительны к разрывам соединений и ошибкам трансляции кодировок.

Рекомендуется использовать кастомный бинарный формат (-Fc) или формат директории (-Fd). Посмотрим на пример команды создания резервной копии:


pg_dump -U postgres -Fc -Z 6 -f /var/archive/complex2020_dev.dump complex2020_dev

Восстановление из такого формата выполняется с помощью специализированной утилиты pg_restore, которая поддерживает многопоточность. Пример восстановления в 4 потока:


pg_restore -U postgres -d db_copy -j 4 --clean --if-exists /var/archive/complex2020_dev.dump

Параметры --clean и --if-exists удаляют объекты базы перед их созданием, что защищает от случайных конфликтов структуры, а параметр -j существенно ускоряет процесс развертывания.

Быстрое клонирование базы без выгрузки в дамп

Если необходимо создать копию базы на том же самом сервере PostgreSQL (например, для разработки или тестирования), нет необходимости тратить время на связку pg_dump и pg_restore. Можно использовать встроенный механизм создания базы по шаблону рабочей базы данных.

Разберем эту процедуру:

  1. В консоли кластера 1С временно устанавливаем блокировку сеансов на исходную рабочую базу и сбрасываем существующие подключения.
  2. Выполняем SQL-команду клонирования: CREATE DATABASE db_copy WITH TEMPLATE complex2020_dev ENCODING 'UTF8';
  3. Снимаем блокировку с исходной рабочей базы.

При таком подходе СУБД выполняет пофайловое копирование на уровне дисковой подсистемы, что происходит в разы быстрее полного цикла выгрузки и загрузки дампа.

← На главную