В статье дан обзор одного из докладов конференции PgConf, которая прошла 23–24 марта 2026 года, Андрея Билле, главного инженера компании Postgres Professional. Название доклада: «Если ваш админ самурай или история о восстановлении очень нужных данных». Этот доклад оказался наиболее зажигательным. Компания Postgres Professional много лет проводит конференцию PgConf и даёт возможность бесплатно участвовать в конференции преподавателям и студентам. Так как я много лет являюсь сертифицированным преподавателем курсов компании Постгрес Профессиональный, то доклады конференции мне особенно интересны.

В докладе рассматривалось восстановление базы данных, у которой не было бэкапа. Использовалась сборка Постгрес от Postgres Professional.

размером 2.5Тб
размером 2.5Тб

Баз в кластере было 10 активно используемых баз данных, размер кластера postgres дорос до 2,5 террабайт. Работало это всё на виртуальной машине. Виртуальный диск создан без предварительного резервирования места и имел размер больше, чем физический диск. Целых 3 года кластер работал без бэкапов и не ломался.

Файловая система хоста (гипервизора) неизвестна, Андрей Билле упоянул, что диск раздувался по «copy on write».

Администраторы баз 1С решают загрузить в кластер ещё одну инфобазу утилитой 1С. Всё настроено «по методичке Антона Дорошкевича», много shared_buffers, исходя из чего Андрей Билле сделал вывод (скорее пошутил) что «всё нормально», так как в методичке не написано про то, что надо бэкапить.

При загрузке в новую инофобазу данных, место на диске, причем гипервизора, заканчивается, так как всё заполнено файлами WAL, которые тоже внезапно перестали удаляться. Реплик нет, вероятная причина — не может выполниться контрольная точка. Файлы WAL удаляет процесс checkpointer в конце контрольной точки. Нет точки — нет удаления.

Операционная система хоста (гипервизор), в которой работает виртуальная машина, посылает уведомление о заканчивающемся месте. Администраторы подсоединяются и удаляют WAL, так как они занимают много места (👆🫣!) и пытаются штатно (в режиме fast) остановить экземпляр постгрес. Андрей Билле сказал: в такой ситуации самое лучшее, что могли бы сделать, это выдернуть шнур питания из розетки.

Экземпляр не останавливается и висит, так как финальная контрольная точка (та, которая выполняется при остановке экземпляра в режиме fast) не может выполниться (то ли начаться, то ли завершиться).

Начат простой и администраторы аварийно (без контрольной точки) останавливают кластер. Останавливают сигналом -9 (SIGKILL) а не SIGQUIT, причем сигналом процессу postmaster.

Скрытый текст

Сигнал 9 нельзя посылать процессам PostgreSQL, а особенно postmaster.

Андрей Билле не стал говорить (сказал только, что у него есть предположения), но из-за большого shared_buffers и быстрого роста файлов при наполнении новой базы натолкнулись на баг, из-за которого контрольная точка не может завершиться и, как следствие, WAL не могут удалиться. Обойти баг можно уменьшив буферный кэш и перегрузить экземпляр.

После всех действий администраторов СУБД разрушается. Утилитой pg_resetwal отключают восстановление при запуске экземпляра (накат WAL). Андрей сказал, что так, как shared_buffers были очень большого размера, повреждений было тоже очень много.

Не стоит доверять методичкам из интернет, подумал я.

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

неоднозначная рекомендация
неоднозначная рекомендация

Я подумал, неужели принято пренебрегать резервированием? Но нет, можно найти методичку для 1С, где написано, что в промышленной эксплуатации наличие реплики обязательно:

правильная рекомендация
правильная рекомендация

После запуска (без наката журнала WAL) экземпляра, приложение 1C не смогло подключиться к СУБД, что неудивительно. Выяснили, что после создания сессии, запросы сложнее select 1; не выполняются. Администраторы стали стучаться во все двери и обратились к Антону Дорошкевичу, рекомендациями которого пользовались. Антон взялся помочь.

Антон давно и тесно работает с Postgres Professional и Андрею Билле начальство сказало: «ты в одной временной зоне с Дорошкевичем и все его проблемы будешь решать ты». Андрей сказал себе, что это нормально, так как не не только у Антона бывают проблемы с PostgreSQL, но и у Postgres Professional бывают проблемы с 1C и их взаимодействие взаимовыгодное.

Андрею консоль к серверу не дали, но так как использовали сборку от Postgres Professional, то в сборке была утилита crash_info, которой Андрей и воспользовался. Эта утилита по 40 сигналу (SIGRTMIN+6) заставляет сбросить дамп состояния процесса операционной системы в файл на диске.

По данным утилиты, серверный процесс, в котором подвисала любая команда, выполняла вызов btmoveright. По сокращению «bt» Андрей понял, что вызов относится к btree index. Догадался, что идёт обращение к индексу на таблицу системного каталога.

Андрей дал задание программисту: «а ты можешь сделать так, чтобы не использовались системные индексы». Программист не стал задавать лишние вопросы и сделал патч. Скомпилировали пропатченную сборку, отдали Антону Дорошкевичу, он отдал клиентам, клиенты установили. Клиенту посоветовали запустить команду перестроения индексов на таблицы системного каталога PostgreSQL, то есть команду REINDEX SYSTEM. Дело было вечером, несмотря на простой базы, все разошлись по домами, а с утра обнаружили, что команда не завершилась.

Позже Андрею подсказали, что патч можно было бы не делать, так как есть параметр конфигурации ignore_system_indexes. Андрей сказал, что он не инженер техподдержки, поэтому все параметры конфигурации (GUC) PostgreSQL он не знает, зато под боком есть программист, которому можно поручить создать патч.

Параметр ignore_system_indexes описан в учебнике Tantor “Администрирование PostgreSQL 17”:

параметр ignore_system_indexes
параметр ignore_system_indexes

Дальше администраторы запустили утилиту pg_dump, но она подвисала на запросе, которым pg_dump в начале работы получает список таблиц, которые нужно выгрузить. Так как системные индексы были отключены, то запрос, который выполняет pg_dump, без индексного доступа выполнялся за неприемлемо большое время, то есть «подвисал».

Андрей Билле сказал, что Антон Дорошкевич сказал в своём докладе, что все данные о таблицах СУБД, 1С хранит в своих таблицах СУБД, а значит список индексов и таблиц из системного каталога не нужен:

Поэтому запустили pg_dump с параметром --data-only, чтобы выгрузить только данные. Утилита снова подвисла. Снова проверили, что делает утилита, она выполняла… тот же запрос. Разработчик (который под боком у Андрея) помог залогировать, что делает pg_dump. pg_dump выгружал не только списки таблиц, индексов, но и еще много совсем ненужного (расширенную статистику):

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

К этому времени СУБД простаивала уже сутки. Создали патч, чтобы запросы утилита pg_dump не выполняла. Поменять что‑либо в СУБД не могли, так как DELETE и DROP подвисали, единственный путь — выгружать данные. Данные хотели скопировать в базы данных другого кластера. Только через сутки одну наиболее важную базу из повреждённого кластера удалось выгрузить, загрузить в новый кластер и «оживить».

По результатам выгрузки, Андрей оформил багрепорт в сообществе PostgreSQL о том, что при отсутствии системных индексов pg_dump долго получает список таблиц и приложил патч неизвестного разработчика из Postgres Pro, который сидел под боком и писал патчи. Жалко, что Андрей не назвал имя разработчика, так как созданный им патч качественный: понятный, неинвазивный, универсальный (подходит для 13–17 версий PostgreSQL).

Скрытый текст

В обсуждении бага, член сообщества, Натан Боссарт отметил «Я не думаю, что это можно считать ошибкой, но избегать запросов pg_dump, когда это возможно, кажется хорошей идеей.» Том Лейн правильно отметил: «Нет оснований полагать, что повреждение каталога преимущественно затрагивает индексы» Так и было — повреждения были рассыпаны во всех объектах, а не только в индексах. Одну базу частично выгрузили, а с частью баз приложение не смогло работать. Тома Лейна беспокоило то, что игнорирование объектов может привести к побочным эффектам если не в настоящем, то в будущем. Дэвид Роули попробовал переписать проблемный запрос, но не получилось.

В результате всех телодвижений, компания, эксплуатировавшая разрушенный кластер баз данных, купила у Postgres Professional техническую поддержку enterprise уровня. Андрей Билле сказал, что именно так и должен выглядеть пресейл, но интуитивно почувствовав ментальное напряжение сотрудников отдела пресейла, сделал оговорку, что, возможно, это и не так.

Скрытый текст

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

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

После доклада задавали вопросы.

Микрофон взял опытный администратор и именно его можно назвать самураем. Самураи не размахивают инструментами, не плодят массово патчи, они используют простой самурайский инструмент и одним движением достигают цели.

— Большое спасибо за доклад. Действительно обнять и плакать.

И вот оно, отточенное движение самурая:

А подскажите, пожалуйста, нельзя ли было заменить pg_dump на COPY?

вопрос про COPY
вопрос про COPY

Андрей Билле моментально всё понял и ответил: можно. Это делает честь Андрею и быстроте его мышления.

Докладчик: Можно, можно, да, наверное, можно. Но вы поймите...

Самурай проворачивает катану: но патч прикольнее

Докладчик:...то, что там 50 000 таблиц только в одной базе. Ну да это можно было.

Самурай: можно было сгенерировать

Докладчик: да, можно было, конечно, скриптик, но, опять же, смогли бы мы, ну да... наверно, смогли бы…

Самурай: то есть, даже не влезая в это (системный каталог)

Докладчик: Да, даже не влезая в это. Да, возможно, можно было. Но тогда бы мы не нашли бы вот эту вот особенность pg_dumpа довольно‑таки странную

Спарринг закончен, делается взаимный поклон:

Самурай: да, согласен. Спасибо Вам.

Докладчик: Да, так можно было сделать это. Прекрасный (вопрос).

Скрытый текст

Участник конференции и на других докладах задавал вопросы. Вопросы были профессиональными и показывали, что он глубоко разбирается в PostgreSQL, быстро схватывает суть доклада.

Например, на утверждение ведущего доклада Александры Бондарь: «это счетчик buffer pin, ничего больше, это не счетчик ожиданий и не счетчик времени ожиданий», участник сразу сказал: «ещё скорость изменения счетчика».

Ведущий: скорость изменения счетчика... это счетчик баффер‑пинов, вы можете их не ждать их при этом, понимаете?

Участник: всё равно — скорость изменения.

Ведущий: скорость изменения — да, но она не гарантирует, что у вас есть проблема.

Участник конференции прекрасно знает, что такое статистика и метрика (производная от статистики). Рост частоты закрепления блоков сам по себе укажет на проблему. Ведущий придаёт событиям ожидания то, чего у них нет и из этого делая ложный вывод, что только wait events способны указывать на проблемы.

Участник

Антон Дорошкевич не согласился с результатом «спарринга» и взял микрофон:

Антон: Андрей, давай я дополню это чуть‑чуть

Докладчик: Угу

Антон: Наверное, можно, но нельзя. Там 50 тысяч таблиц, неважно. 58 баз по десяткам тысяч таблиц. Проблема в том, что мы не имеем средств. Опа, батарейка кончается (микрофон намекал, что не надо продолжать). Не могли средствами постгреса получить список таблиц.

Но позвольте, любому в зале было понятно, что выгружали --data-only, да и 1С хранит список таблиц у себя, о чём сказал докладчик.

Докладчик увещевает Антона: не, ну мы же его отключили, мы потом уже смотрим

Антон, подняв указательный палец вверх продолжил: Часами, на одну базу

Василий Пучков потянулся к носу (зеркальные нейроны запустили "эффект Пиноккио", что означает сомнения), зрители смотрят на Антона с недоумением
Василий Пучков потянулся к носу (зеркальные нейроны запустили "эффект Пиноккио", что означает сомнения), зрители смотрят на Антона с недоумением

То, что Антон говорил в микрофон дальше — не играет роли. Даже если 1С хранит списки таблиц в бинарном виде, это не важно, ведь таблица pg_class — это тоже таблица. Если хотели выгрузить 50 000 таблиц, то можно было бы начать с выгрузки содержимого pg_class и получить имена таблиц для команды COPY:

copy (select relnamespace, relname 
    from pg_class where relkind='r') 
to '/tmp/pg_class.txt'

Если кликнуть на SourceCraft, в последнем абзаце будет объяснение команды.

Можно ли Антону было «вырулить»? Как вариант: сказать, что был вечер, все устали, про COPY не подумали. В стрессовых ситуациях совершается много ошибок, это всем понятно. Цель вопроса про COPY — выяснить как лучше делать, если такое возникнет. И оратору достаточно подтвердить, что да, COPY в такой ситуации — лучшее решение. Андрей Билле подтвердил и вышел с достоинством. В комментариях к этой статье Антон написал, что он хотел сказать.

Создание патчей (индивидуальных сборок) полезно тем, что в результате клиент купил техподдержку. Если предложить дать команду COPY, то она вряд ли впечатлит. Но техническая поддержка полезна в любом случае. Также полезно выписать для себя профильные рассылки или чаты, где можно задать вопросы пользователям, думаю отговорили бы от стирания WAL и подсказали бы идею с COPY. Для 1С есть профильный чат в телеграм «PostgreSQL + 1C + Linux» с 4000 участников.

Чат приносит пользу: в нём впервые была описана проблема с потоковым чтением в локальный буфер, появившаяся в 18 версии PostgreSQL

set effective_io_concurrency = 64;
create temp table t1 (a char(1700));
insert into t1 select 'a' from generate_series(1,20000);
create temp table t2 (a char(1700));
insert into t2 select * from t1;
SET
CREATE TABLE
INSERT 0 20000
CREATE TABLE
ERROR:  no empty local buffer available

Заключение

Не стоит эксплуатировать базу, в которой хранятся нужные данные без реплик, бэкапов или хотя бы дампов.

Если структура и набор таблиц нечасто меняется, то, на всякий случай, стоит иметь скрипт создания таблиц и других объектов, который создаёт утилита pg_dump с параметром ‑schema‑only.

Стоит рассмотреть самые простые пути решения проблемы, а не менять ядро PostgreSQL.

Если в методичке Антона Дорошкевича не упомянуты реплики и бэкапы, это не значит, что их не нужно делать. Например, более квалифицированные специалисты 1С http://www.gilev.ru/pgbackup/ пишут, что бэкапы важны:

о важности уметь делать бэкапы, особенно в PostgreSQL
о важности уметь делать бэкапы, особенно в PostgreSQL

Эта статья не обзор докладов конференции, как в статье про PGBootCamp.

Из других докладов упомяну только, что был исправлен неприятный баг в коде мультитранзакций. Компания Дмитрия натолкнулась на этот баг при реальной работе. 12 февраля 2026 года были выпущены минорные обновления, в которых баг был исправлен:

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

Зачем я упомянул этот доклад? Технической причиной разрушения кластера баз данных из доклада Андрея Билле был или мог быть баг с невыполнением контрольной точки на большом буферном кэше под большой нагрузкой. Резервирование бы спасло, но баг с мультитранзакциями затрагивает тех, кто резервирует. Проще говоря, кроме резервирования, ещё стоит не забывать устанавливать минорные обновления.