Администрирование баз данных 1С на СУБД PostgreSQL имеет ряд важных особенностей, связанных со спецификой платформы «1С:Предприятие». Одной из наиболее частых проблем, с которой сталкиваются системные администраторы и разработчики при попытке автоматизировать восстановление баз из логических дампов (созданных через pg_dump), является ошибка отсутствия типов данных: «тип public.mvarchar не существует».
В этой статье мы подробно разберем, почему возникает данная ошибка, проанализируем архитектуру хранения специфических типов 1С в PostgreSQL, рассмотрим классический скрипт резервного копирования и изучим самый безопасный и отказоустойчивый метод восстановления базы данных «на лету» без остановки всего кластера 1С.
Для обеспечения совместимости поведения PostgreSQL с СУБД MS SQL Server (в части сравнения строк, обработки концевых пробелов и работы с регистром) компания 1С совместно с разработчиками Postgres Pro использует специальное расширение СУБД, добавляющее типы данных mchar и mvarchar. Эти типы разворачиваются внутри схемы public вашей базы данных при её первом создании средствами платформы 1С.
Когда мы пытаемся сделать выгрузку базы через стандартную утилиту СУБД со специальным ключом очистки:
pg_dump.exe --clean --format=plain ...
утилита генерирует в начале SQL-файла команды удаления существующих объектов (таких как DROP TABLE, DROP VIEW, а также DROP TYPE и DROP FUNCTION), чтобы перед импортом полностью очистить целевую базу. При попытке выполнить этот сценарий в одной транзакции (с ключом --single-transaction) или при строгой обработке ошибок (ON_ERROR_STOP=on) СУБД выдает ошибку:
тип "public.mvarchar" не существует (или блокирует его удаление, так как на него завязаны другие системные функции расширения).
Попытки использовать ключ --if-exists спасают не во всех конфигурациях баз, а игнорирование ошибок (отключение строгого режима) приводит к тому, что скрипт восстановления завершается со статусом ошибки (код возврата 1), что делает невозможным качественный автоматический контроль резервного копирования в скриптах PowerShell, Bash или специализированных программах (например, в Обновляторе 1С).
Удаление и полное пересоздание базы в СУБД перед импортом тоже вызывает проблему: кластер 1С «держит» соединения с базой данных, блокируя выполнение команды DROP DATABASE на стороне PostgreSQL.
---
Для решения этой проблемы разработана и успешно применяется профессиональная схема восстановления «на лету» через временную базу данных. Её главное преимущество — высокая отказоустойчивость. Если в процессе импорта дампа произойдет какая-либо ошибка (например, повредится файл архива или отключится питание), исходная рабочая база никак не пострадает и продолжит функционировать. Пользователи не потеряют доступ к старым данным в случае аварии при восстановлении.
Рассмотрим по шагам этот алгоритм.
Для создания логического слепка базы данных используем утилиту pg_dump. Обратите внимание, что мы не используем ключ --clean, чтобы избежать проблем со специфическими типами 1С в результирующем файле:
"C:\Program Files\PostgreSQL\bin\pg_dump.exe" --quote-all-identifiers --format=plain --dbname=postgresql://"USER":"PASSWORD"@"HOST:PORT"/"BASE1C" --file="C:\Backup\backup.sql"
Для восстановления мы подготавливаем абсолютно чистую базу данных в СУБД с временным именем (например, temp_restore). В качестве шаблона обязательно указываем стандартный системный шаблон:
"C:\Program Files\PostgreSQL\bin\createdb.exe" --encoding=utf8 --template=template1 --username="USER" --host="HOST" --port=PORT temp_restore
Разворачиваем наш SQL-файл резервной копии во вновь созданную базу temp_restore. Так как база была абсолютно пустой, никаких конфликтов со старыми таблицами или типами данных mvarchar гарантированно не возникнет:
"C:\Program Files\PostgreSQL\bin\psql.exe" --single-transaction --echo-errors --quiet --set="ON_ERROR_STOP=on" --file="C:\Backup\backup.sql" --dbname=postgresql://"USER":"PASSWORD"@"HOST:PORT"/"temp_restore"
Если на данном шаге возникнет ошибка импорта, процесс прервется, но наша основная рабочая база BASE1C останется целой и невредимой.
Перед тем как подменить базы в СУБД, необходимо отключить активных пользователей и фоновые задания. Сделать это можно программно через COM-соединение, утилиту администрирования rac или консоль администрирования кластера 1С:
BASE1C в PostgreSQL.Теперь, когда СУБД освободила базу от блокировок кластера 1С, мы можем мгновенно переименовать базы данных. Сначала переименовываем рабочую базу в резервную (на случай, если потребуется быстрый откат):
"C:\Program Files\PostgreSQL\bin\psql.exe" --dbname=postgresql://"USER":"PASSWORD"@"HOST:PORT"/"template1" --command="ALTER DATABASE BASE1C RENAME TO BASE1C_OLD;"
Затем переименовываем нашу временную базу temp_restore, в которую мы только что успешно залили бэкап, в имя основной рабочей базы:
"C:\Program Files\PostgreSQL\bin\psql.exe" --dbname=postgresql://"USER":"PASSWORD"@"HOST:PORT"/"template1" --command="ALTER DATABASE temp_restore RENAME TO BASE1C;"
После успешной рокировки возвращаем настройки в кластере 1С в исходное состояние:
BASE1C в свойствах информационной базы в консоли кластера 1С.Убедившись, что пользователи успешно заходят и работают в восстановленной базе данных, мы можем окончательно удалить старую копию базы СУБД (бывшую рабочую базу, переименованную в BASE1C_OLD) для освобождения дискового пространства:
"C:\Program Files\PostgreSQL\bin\dropdb.exe" --username="USER" --host="HOST" --port=PORT BASE1C_OLD
---
Процедуру из Шага 4 по высвобождению базы в кластере 1С можно значительно ускорить и упростить, выполнив принудительный сброс соединений напрямую на уровне СУБД PostgreSQL. Для этого выполним следующий SQL-запрос под учетной записью суперпользователя СУБД:
-- Запрещаем новые подключения к рабочей базе данных
ALTER DATABASE BASE1C CONNECTION LIMIT 0;
-- Принудительно разрываем все существующие активные сессии
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE datname = 'BASE1C' AND pid <> pg_backend_pid();
После выполнения этих команд база данных мгновенно освобождается от блокировок со стороны сервера приложений 1С, что позволяет сразу же запустить команды переименования баз (Шаг 5).
---
В среде администраторов баз данных 1С часто ведется спор о терминологии и применимости утилиты pg_dump. Важно понимать разницу между терминами.
Логический дамп (выгрузка) — это текстовый (или сжатый) файл, содержащий инструкции на языке SQL для воссоздания структуры таблиц и заполнения их данными (команды CREATE TABLE, INSERT и т.д.). Именно это делает утилита pg_dump. По своей сути это близко к выгрузке информационной базы 1С в файл .dt, но выполняется на уровне СУБД.
Физическая резервная копия (бэкап) — это побитовая/побайтовая копия физических файлов СУБД, расположенных на диске. Она создается с помощью специализированных утилит резервного копирования.
bytea (в частности, в таблице public.config). При конвертации больших двоичных объектов в текстовый SQL-формат утилитой pg_dump этот лимит может быть превышен, что приведет к аварийному завершению работы с ошибкой памяти.pg_dump невозможно делать инкрементные бэкапы или восстанавливать базу на определенный момент времени (технология PITR - Point-in-Time Recovery).Для крупных и высоконагруженных промышленных баз 1С на PostgreSQL рекомендуется использовать инструменты физического резервного копирования, такие как утилита pg_probackup или связка утилиты pg_basebackup с непрерывным архивированием журналов предзаписи (WAL).
Тем не менее, для небольших баз данных, а также для создания гарантированной "страховочной" точки восстановления непосредственно перед процедурой обновления конфигураций 1С (как это делает инструмент "Обновлятор 1С"), логические дампы через pg_dump по-прежнему остаются отличным, простым и очень надежным инструментом.