Как решить проблему с архивацией базы данных 1С на СУБД PostgreSQL (ошибка pg_dump: invalid memory alloc request size)?

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

При администрировании крупных баз данных 1С:Предприятие на СУБД PostgreSQL системные администраторы часто сталкиваются с внезапным отказом штатных средств резервного копирования. Ошибка обычно проявляется при использовании стандартной утилиты pg_dump и сопровождается следующим аварийным сообщением:

pg_dump: Ошибка выгрузки таблицы "config": сбой в PQgetResult(). Сообщение об ошибке с сервера: Р?РЁР?Р'Р?Р?: invalid memory alloc request size 1174829507. Выполнялась команда: COPY public.config (filename, creation, modified, attributes, datasize, binarydata) TO stdout;

Эта проблема чаще всего затрагивает конфигурации с долгой историей развития, такие как «1С:Комплексная автоматизация 1.1» (КА), «1С:Управление производственным предприятием 1.3» (УПП), а также крупные отраслевые решения на их базе. Давайте подробно разберем технические причины этого сбоя и рассмотрим пошаговые сценарии его гарантированного устранения.

В чем заключается техническая причина ошибки?

Для того чтобы понять природу возникновения этой ошибки, проанализируем структуру хранения метаданных в базах данных платформы 1С. Файл конфигурации 1С (расширение .cf) записывается в системную таблицу config в виде двоичных данных (тип данных bytea или BLOB). В таблице config за хранение самого файла конфигурации отвечает поле binarydata.

Когда конфигурация находится на поддержке с возможностью изменения, СУБД вынуждена хранить сразу несколько версий метаданных: основную конфигурацию и конфигурацию поставщика. Суммарный объем одной строки с конфигурацией поставщика в поле binarydata может легко превысить 500 Мегабайт.

При запуске резервного копирования через утилиту pg_dump происходит следующее:

  1. Утилита pg_dump выполняет выгрузку данных таблицы через SQL-команду COPY ... TO stdout.
  2. Для передачи двоичных данных (тип bytea) в текстовом потоке резервной копии СУБД PostgreSQL производит экранирование (кодирование) бинарного поля в текстовый формат (hex-формат или octal). При этом кодировании каждый байт двоичных данных превращается в 2 байта текста (а с учетом управляющих символов объем может вырасти еще больше).
  3. В СУБД PostgreSQL исторически заложено жесткое архитектурное ограничение: размер буфера памяти под одну операцию выделения памяти (функция palloc в исходном коде) не может превышать 1 Гигабайт (точнее, значение макроса MaxAllocSize, равное 0x3FFFFFFF байт или 1 073 741 823 байта).
  4. Если исходный размер конфигурации поставщика в поле binarydata составляет, например, 550 Мегабайт, то при конвертации в текстовое представление СУБД пытается выделить буфер памяти размером более 1,1 Гигабайта.
  5. Система натыкается на внутренний лимит безопасности PostgreSQL, прерывает операцию резервного копирования и выдает ошибку invalid memory alloc request size.

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

---

Решение №1. Секционирование процесса резервного копирования (Схема + Данные + Бинарный экспорт таблицы Config)

Наиболее изящным и безопасным способом решения проблемы без изменения структуры метаданных и конфигурации 1С является разделение процесса создания бэкапа на три независимых этапа. Мы исключим проблемную таблицу config из общего текстового дампа и выгрузим ее отдельно в "сыром" бинарном виде, который не требует перекодирования в текст и не вызывает переполнения буфера памяти.

Рассмотрим по шагам автоматизированный скрипт резервного копирования для операционной системы Linux:


#!/bin/bash
# Настройка переменных окружения
DB_NAME="firm_db"
BACKUP_DIR="/var/backups/1c"
DATE=$(date +%Y_%m_%d_%H%M)

# Шаг 1. Выгрузка основного дампа всей базы данных ЗА ИСКЛЮЧЕНИЕМ данных таблицы config
pg_dump -U postgres -F c -Z 9 -T public.config -f "${BACKUP_DIR}/${DB_NAME}_data_${DATE}.backup" "${DB_NAME}"

# Шаг 2. Выгрузка только структуры (схемы) таблицы config без самих данных
pg_dump -U postgres -t public.config -s -f "${BACKUP_DIR}/${DB_NAME}_config_schema_${DATE}.sql" "${DB_NAME}"

# Шаг 3. Прямая бинарная выгрузка данных таблицы config через механизм COPY WITH BINARY
psql -U postgres -d "${DB_NAME}" -c "COPY public.config TO '${BACKUP_DIR}/${DB_NAME}_config_data_${DATE}.bin' WITH BINARY;"

Проанализируем процесс восстановления такой резервной копии. При возникновении аварийной ситуации развертывание базы данных из трех полученных файлов необходимо выполнять в строго определенном порядке:

  1. Создаем чистую пустую базу данных на сервере PostgreSQL.
  2. Восстанавливаем основной архив с данными (база восстановится полностью, но без таблицы config):
    
    pg_restore -U postgres -d firm_db /var/backups/1c/firm_db_data_YYYY_MM_DD_HHMM.backup
    
  3. Создаем структуру пустой таблицы config из сохраненного SQL-файла схемы:
    
    psql -U postgres -d firm_db -f /var/backups/1c/firm_db_config_schema_YYYY_MM_DD_HHMM.sql
    
  4. Заливаем сохраненные бинарные данные конфигурации обратно в созданную таблицу:
    
    psql -U postgres -d firm_db -c "COPY public.config FROM '/var/backups/1c/firm_db_config_data_YYYY_MM_DD_HHMM.bin' WITH BINARY;"
    

Важное предупреждение: Метод COPY ... WITH BINARY является платформозависимым. Настоятельно рекомендуем разворачивать полученный бинарный файл данных на СУБД аналогичной архитектуры (например, перенос с x64 на x64) и той же мажорной версии PostgreSQL во избежание несовместимости форматов хранения.

---

Решение №2. Использование механизмов физического резервного копирования

Если логическое резервное копирование через pg_dump продолжает вызывать трудности, имеет смысл полностью перевести контур резервного копирования на физический уровень. При физическом копировании СУБД работает непосредственно с файлами табличных пространств на диске (побайтное копирование страниц памяти) и не производит никаких высокоуровневых преобразований данных в текст. Ограничение в 1 ГБ памяти здесь не играет роли.

Для создания надежных инкрементных и полных физических бэкапов рекомендуется использовать специализированные утилиты:

Посмотрим на пример использования pg_basebackup для создания транзакционно согласованной физической копии:


pg_basebackup -h localhost -U postgres -D /var/backups/physical/base_backup_directory -F t -z -P

Этот метод гарантирует 100% стабильность создания архива вне зависимости от размера конфигурации 1С и объема отдельных полей СУБД.

---

Решение №3. Включение специализированных опций в российских форках PostgreSQL (Postgres Pro Enterprise / Tantor)

Поскольку проблема с ограничением буфера памяти при выгрузке больших объектов (LOBs) в базах 1С хорошо известна отечественным разработчикам СУБД, в специализированных российских дистрибутивах PostgreSQL были внедрены встроенные параметры для обхода этой ошибки.

Если вы используете коммерческую версию Postgres Pro Enterprise (начиная с релиза 15.2.1 и старше), вы можете использовать специальный параметр enable_large_mem_buffers. Он расширяет максимально допустимый размер выделяемой памяти под текстовое представление объектов bytea до 2 Гигабайт.

Для активации возможности выгрузки больших конфигураций выполните следующую команду в консоли СУБД или добавьте параметр в файл конфигурации postgresql.conf:


ALTER SYSTEM SET enable_large_mem_buffers = on;
SELECT pg_reload_conf();

При использовании утилиты pg_dump из этого пакета обязательно передавайте специализированный флаг:

pg_dump -U postgres --enable-large-mem-buffers -F c -f /arc/my_db.backup my_db

Если ваша инфраструктура развернута на базе операционной системы Astra Linux с СУБД Tantor Special Edition, аналогичного результата можно добиться включением параметра enable_large_allocations:


# В файле postgresql.conf установите параметр:
enable_large_allocations = on

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

---

Решение №4. Снятие конфигурации 1С с поддержки поставщика

Если база данных находится на поддержке, но при этом активно дорабатывается программистами, СУБД вынуждена хранить внутри таблицы config избыточные данные поставщика (зачастую дублирующиеся). Если полностью снять конфигурацию с поддержки (перевести в статус "Конфигурация находится на поддержке с возможностью изменения" с полным удалением исходных файлов поставщика или полностью снять замок), размер таблицы config сократится практически в два раза.

Проанализируем, как правильно произвести эту операцию в Конфигураторе 1С:

  1. Откройте базу данных 1С в режиме Конфигуратор.
  2. Перейдите в главное меню: Конфигурация -> Поддержка -> Настройка поддержки.
  3. В открывшемся окне нажмите кнопку Включить возможность изменения (если она еще не включена) или нажмите кнопку Снять с поддержки.
  4. Подтвердите действие. При этом из базы данных удалятся дублирующие конфигурационные файлы поставщика, занимающие сотни Мегабайт в таблице config.
  5. Выполните сохранение изменений (клавиша F7).
  6. Запустите тестирование и исправление информационной базы или выполните команду VACUUM FULL config; в консоли PostgreSQL для очистки дискового пространства и дефрагментации таблицы.

После проведения данной процедуры размер поля binarydata уменьшится до приемлемых 300-450 Мегабайт, и стандартная утилита pg_dump начнет отрабатывать в штатном режиме без ошибок выделения памяти.

---

Решение №5. Оптимизация размера конфигурационного файла (.cf)

Зачастую размер конфигурации раздувается из-за нерационального хранения двоичных данных непосредственно внутри метаданных 1С. Разработчики могут хранить в макетах भारी файлы, такие как:

Проанализируем конфигурацию на наличие "тяжелых" объектов метаданных. Откройте конфигурацию, перейдите в раздел Общие -> Общие макеты и просмотрите двоичные макеты. Удаление устаревших драйверов торгового оборудования, внешних компонент или перенос тяжелых инструкций во внешние файловые ресурсы позволят сократить размер файла конфигурации (.cf) ниже критической отметки в 500 Мегабайт. Как только чистый размер конфигурации уменьшится, СУБД PostgreSQL сможет успешно преобразовывать бинарное поле в текст при выгрузке резервной копии.

← На главную