Как исправить ошибку PostgreSQL invalid memory alloc request size 18446744073709551613 в базе 1С

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

При работе с базами данных 1С на платформе PostgreSQL системные администраторы иногда сталкиваются с критической ошибкой ERROR: invalid memory alloc request size 18446744073709551613. Эта ошибка сопровождается состоянием XX000 и приводит к полной невозможности обращения к конкретной таблице или справочнику. Любые действия, будь то чтение данных, попытка выгрузки в .dt или создание бэкапа средствами СУБД, завершаются аварийно.

В этой статье мы подробно разберем природу этой ошибки, выясним причины ее возникновения и рассмотрим несколько способов восстановления работоспособности базы данных — от точечного удаления поврежденных записей до полного пересоздания структуры таблицы.

Анализируем причину возникновения ошибки

Прежде всего, проанализируем само число 18446744073709551613. Оно не случайно. В 64-битной архитектуре это результат интерпретации отрицательного числа как беззнакового целого (unsigned integer). Математически это 2^64 - 3. В контексте PostgreSQL такая ситуация обычно указывает на повреждение заголовка varlena (переменной длины данных).

Чаще всего проблема кроется в технологии TOAST (The Oversized-Attribute Storage Technique). PostgreSQL использует TOAST для хранения длинных строк или неограниченных полей, которые не помещаются в стандартную страницу данных (8 КБ). Если заголовок записи в основной таблице ссылается на TOAST-таблицу, но физические данные там повреждены (например, из-за сбоя файловой системы или диска), СУБД считывает некорректную длину, пытается выделить под нее невообразимый объем памяти и «падает» с указанной ошибкой.

Шаг 1: Идентификация проблемной таблицы и файла

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

SELECT pg_relation_filepath('имя_таблицы_в_субд');

Этот запрос вернет относительный путь к файлу в директории data. Зная этот путь, мы сможем проверить состояние файловой системы или попытаться восстановить файл из теневых копий (VSS), если они настроены на сервере Windows.

Шаг 2: Метод «Бинарного поиска» поврежденной строки

Если нам нужно сохранить данные, попробуем локализовать конкретную «битую» запись. Поскольку ошибка возникает при попытке прочитать данные, мы можем перебирать строки порциями. Разберем этот процесс подробнее:

  1. Выполняем запрос с ограничением выборки: SELECT * FROM имя_таблицы LIMIT 100 OFFSET 0;
  2. Если запрос прошел успешно, увеличиваем OFFSET на 100.
  3. Как только запрос выдает ошибку invalid memory alloc request size, мы понимаем, что поврежденная запись находится в текущем интервале.
  4. Сужаем диапазон поиска (по 10 строк, затем по одной), пока не найдем конкретный идентификатор _IDRRef или системный адрес ctid.

Важно: Для ускорения поиска и исключения влияния индексов, рекомендуется отключить индексное сканирование в сессии:


SET enable_indexscan = off;
SET enable_bitmapscan = off;

Шаг 3: Точечное удаление через ctid

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

DELETE FROM имя_таблицы WHERE ctid = '(номер_страницы, номер_строки)';

Рассмотрим ситуацию, когда стандартное удаление не срабатывает. В этом случае можно воспользоваться параметром zero_damaged_pages. Эта настройка заставляет PostgreSQL игнорировать поврежденные заголовки страниц, обнуляя их содержимое и позволяя продолжить чтение.


SET zero_damaged_pages = on;
VACUUM FULL имя_таблицы;
SET zero_damaged_pages = off;

Внимание: Использование zero_damaged_pages приведет к безвозвратной потере данных в поврежденной странице, но это позволит «очистить» таблицу и вернуть ей работоспособность для остальных данных.

Шаг 4: Радикальное решение — Пересоздание таблицы

Если справочник не является критически важным (как в случае автора темы с справочником «Документы физических лиц»), или если битых записей слишком много, самым быстрым и надежным способом будет полное пересоздание таблицы. Рассмотрим пошаговый алгоритм действий:

  1. Обязательно создаем копию всей папки data при остановленной службе PostgreSQL. Это наша страховка.
  2. Заходим в консоль pgAdmin или psql.
  3. Удаляем поврежденную таблицу командой DROP TABLE имя_таблицы CASCADE;. Параметр CASCADE удалит также связанные индексы.
  4. Создаем таблицу заново. Скрипт создания можно взять из аналогичной чистой базы той же версии конфигурации.
  5. В режиме 1С:Предприятие выполняем процедуру «Тестирование и исправление» (ТиИ) с установленной галочкой «Очистка ссылок на несуществующие объекты». Это удалит «битые» ссылки в других таблицах, которые указывали на удаленные записи.

Посмотрим на пример того, как это было реализовано в сообщении автора. Поскольку данные были в старом бэкапе, после пересоздания пустой таблицы данные были перенесены с помощью универсальной обработки выгрузки/загрузки XML, что позволило сохранить внутренние идентификаторы (GUID) и избежать появления битых ссылок в других документах. Для поиска возможных расхождений в проводках после такого переноса данных применяется автоматическая сверка бухгалтерских и налоговых проводок между восстановленной базой и бэкапом.

Шаг 5: Проверка после восстановления

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

pg_dump -U postgres -d имя_базы > backup.sql

Если pg_dump завершился без ошибок, значит, физическая целостность структуры восстановлена. В самой 1С рекомендуется запустить полное Тестирование и исправление, чтобы убедиться в логической целостности данных на уровне платформы.

Подводя итог, отметим, что ошибка invalid memory alloc request size — это сигнал о физическом повреждении. При ее появлении следует первым делом проверить исправность дисковой подсистемы и оперативной памяти сервера, чтобы исключить повторение ситуации в будущем.

← На главную