При администрировании баз данных 1С на СУБД PostgreSQL системные администраторы часто сталкиваются с неприятной ситуацией: при попытке выполнить стандартную операцию «Выгрузить информационную базу» (создание файла .dt) процесс аварийно прерывается. На экране появляется системное сообщение: «Ошибка СУБД: ERROR: unexpected out-of-memory...» (в полной формулировке — unexpected out-of-memory situation during sort или unexpected out-of-memory situation in tuplestore).
В этой статье мы подробно разберем, почему возникает этот сбой, проанализируем внутренние механизмы взаимодействия 1С и PostgreSQL, а также рассмотрим пошаговые методы устранения данной ошибки.
Выгрузка информационной базы в файл .dt — это специфическая процедура платформы 1С. В отличие от стандартного резервного копирования средствами СУБД (например, утилиты pg_dump), выгрузка в .dt представляет собой последовательное чтение всех таблиц базы данных самой платформой 1С. Платформа запрашивает данные, СУБД производит выборки, выполняет масштабные операции сортировки и передает информацию клиенту. Именно в процессе этих интенсивных выборок и сортировок на стороне СУБД происходит критический сбой распределения памяти.
Для того чтобы понять природу ошибки, обратимся к исходному коду СУБД PostgreSQL. В версиях семейства 9.3 (включая популярную сборку 9.3.4-1.1C), а также в ранних минорных релизах веток 9.4 и 9.5 присутствовал зарегистрированный разработчиками баг (Bug #13530).
Проблема кроется в модуле tuplestore.c, который отвечает за временное хранение кортежей данных при выполнении сортировки во внешней памяти. Когда СУБД понимает, что объем сортируемых данных превышает лимит, выделенный в оперативной памяти, запускается алгоритм масштабирования массивов адресации. Из-за некорректного математического расчета накладных расходов на адресацию указателей СУБД ошибочно считала, что доступная память полностью исчерпана (так называемое состояние LACKMEM). База данных аварийно прекращала выполнение тяжелого запроса с ошибкой «out-of-memory», хотя физически на сервере могло оставаться свободным огромное количество оперативной памяти.
Ниже мы подробно разберем три основных способа решения этой проблемы, начиная с самого быстрого обходного пути и заканчивая фундаментальным обновлением ПО.
Программная ошибка в модуле tuplestore наиболее часто проявляет себя, когда для сессий пользователей выделено небольшое количество рабочей памяти. За это отвечает параметр work_mem в конфигурационном файле СУБД. По умолчанию этот параметр может быть настроен всего на 4MB или 8MB. При обработке гигантских таблиц 1С этого объема не хватает, данные начинают сбрасываться на диск во временные файлы, активируя ошибочный код СУБД.
Для того чтобы обойти этот баг, увеличим объем оперативной памяти, выделяемой под каждую операцию сортировки:
/var/lib/pgsql/data/postgresql.conf (в ОС Linux) или в папке установки PostgreSQL в каталоге data (в ОС Windows).work_mem. По умолчанию она может быть закомментирована знаком #.
# Открываем postgresql.conf и правим параметр:
work_mem = 128MB
Важное предупреждение: Параметр work_mem выделяется под каждую отдельную операцию сортировки внутри каждого активного запроса. Если на сервере одновременно работает много пользователей, суммарное потребление памяти СУБД может резко вырасти. Не устанавливайте этот параметр в экстремально высокие значения (например, несколько гигабайт), иначе операционная система может принудительно завершить процесс PostgreSQL по нехватке реальной ОЗУ (работа механизма OOM Killer).
systemctl restart postgresql-9.3
Поскольку проблема является официально признанным багом, разработчики оперативно внесли исправления в исходный код СУБД. Для полного устранения уязвимости без необходимости искусственного завышения параметров памяти рекомендуется обновить PostgreSQL.
Перед обновлением обязательно сделайте резервную копию всей директории данных СУБД (PGDATA) методами физического копирования файлов при остановленной службе сервера баз данных.
Иногда ложное срабатывание лимитов памяти провоцируется накопившимся "мусором" в таблицах СУБД (старыми версиями строк) или некорректным расчетом планов запросов из-за неактуальной статистики базы данных. Чтобы минимизировать нагрузку на память при выгрузке, выполним профилактические регламентные работы.
Проведем обслуживание на стороне PostgreSQL. Подключимся к базе данных через консоль psql или утилиту pgAdmin и выполним команду полной очистки и обновления статистики:
-- Полная очистка таблиц от устаревших записей и обновление статистических данных
VACUUM FULL ANALYZE;
Данная команда заблокирует таблицы базы данных на время выполнения, перестроит файлы данных на диске, освободит неиспользуемое пространство и обновит статистику. После этого планировщик PostgreSQL будет строить более оптимальные планы выполнения запросов, требующие гораздо меньше ресурсов для сортировок.
Также рекомендуется провести обслуживание средствами самой платформы 1С:
Реиндексация таблиц информационной базы и Проверка логической целостности информационной базы..dt.Использование связки из обновления СУБД (или корректировки параметра work_mem) и регулярного обслуживания баз данных гарантирует стабильное создание файлов резервных копий 1С без прерываний и зависаний системы.