Хабрахабр

Простите, я сломал ваш recovery.conf

i break you recoveryВ PostgreSQL начиная с очень давних времён аж версии 8.0 вышедшей в далёком 2005 году для восстановления в определённую точку времени использовался специальный файл конфигурации recovery.conf. Этот же файл впоследствии стал использоваться для режима standby и потоковой репликации.

И если для point-in-time recovery который нужен реже чем раз в год с этим смириться ещё можно, то вот необходимость рестарта всей базы для изменения адреса upstream сервера репликации несколько удручает. Однако начиная со следующего релиза PostgreSQL 12 больше recovery.conf работать не будет: я его сломал.
Но зачем?
Была у recovery.conf одна особенность: читался он только при старте СУБД. Видел разные способы извращений для обхода этого ограничения вроде использования L3 роутинга, схемы с каскадными репликациями (чтобы соответственно перезапускать не все реплики, а хотя бы только часть) и даже (хоть в production не встречал) walbouncer.

Оказалось всё плохо. После очередного планового рестарта реплик только из-за необходимости изменить параметры репликации решил я поковырять, а чего будет стоить научить PostgreSQL перечитывать primary_conninfo по SIGHUP? Осталось корректно это реализовать. В принципе, необходимо поменять всего одну переменную в startup процессе и оттуда же запросить рестарт WalReceiver — и на этом всё, репликация продолжится с новым адресом корректно. Несколько недель спустя я закончил патч с реализацией перечитывания recovery.conf по SIGHUP сигналу, при этом тот патч никак не ломал имеющееся поведение базы.

На что довольно быстро ответил Michael Paquier:
Затем, набравшись смелости, отправил его в список рассылок разработчиков PostgreSQL.

Before making some of them as reloadable, let's switch them to be GUCs first and not re-invent the SIGHUP handling of parameters as your patch does.

Упс, оказалось, что я задавал поисковику неправильный вопрос. Спрашивать надо было не про перечитывание recovery.conf, а о превращении параметров из живущего отдельно recovery.conf в инфраструктуру GUC (grand unified configuration), используемую для всех остальных параметров СУБД. То есть однозначно нет, такой патч нам не нужен, такое мы не хотим. Давайте сначала перенесём все эти настройки из recovery.conf в нашу стандартную инфраструктуру настроек.

Почитал архивные обсуждения по правильному поисковому запросу, открыл последнее найденное обсуждение переноса настроек (ссылку любезно предоставил Michael Paquier в своём ответе, за что ему отдельное спасибо, как и за быстрый ответ). На этом невесёлом известии я погоревал и подумал: «А вот давайте перенесём!». Значит, отсюда и начнём. На тот момент мая 2018 года патч был заброшен уже больше года. По плану развлечения: Или правильнее сказать «продолжим»?

  1. прочитать и составить список правок к последней опубликованной версии патча
  2. разобрать изменения в патче и перенести нужное на актуальную версию кодовой базы
  3. исправить все упоминания recovery.conf и его параметров в документации
  4. починить тесты
  5. отправить новый патч в список рассылок
  6. получить какие-нибудь отклики
  7. чего-нибудь поправить согласно пожеланиям и вернуться на пункт 5
  8. получить ещё раз отказ в принятии патча (через годик-полтора)

Похоже на план действий? Ну вот и двигаемся по нему!

Затем 3 месяца в гнетущей тишине леденящего душу молчания рыбы Баскервилей. Долго ли, коротко ли, добрался до пункта номер пять и 21 июня 2018 года опубликовал новую версию патча, в новой ветке обсуждений. Спустя несколько итераций правок, пока я тихо-мирно уехал на несколько дней погулять-посмотреть Будапешт и осматриваю достопримечательности, вдруг приходит обескураживающее письмо от Peter Eisentraut:
На исходе сентября неожиданно к патчу проявляет интерес Peter Eisentraut — один из Core разработчиков с правом коммита.

I have also updated the documentation more extensively. I went over the patch and did a bunch of small refinements. The attached patch is committable to me.

То есть, Peter Eisentraut поправил ещё некоторые мелочи по своему усмотрению, обновил документацию, сжёг целиком раздел recovery-config.sgml и считает, что в таком виде патч уже можно принимать. Ой, а я думал это случится только для postgresql 13, даже если так очень повезёт, что патч вообще дойдет до состояния готовности к коммиту.

И несколькими днями спустя, а именно 25 ноября этого 2018 года, Peter Eisentraut действительно принимает этот патч:

Currently, all the affected settings are PGC_POSTMASTER; this could be refined in the future case by case.
Recovery is now initiated by a file recovery.signal. recovery.conf settings are now set in postgresql.conf (or other GUC sources). The standby_mode setting is gone. Standby mode is initiated by a file standby.signal. If a recovery.conf file is found, an error is issued.
The trigger_file setting has been renamed to promote_trigger_file as part of the move.
The documentation chapter «Recovery Configuration» has been integrated into «Server Configuration».
pg_basebackup -R now appends settings to postgresql.auto.conf and creates a standby.signal file.
Author: Fujii Masao <masao(dot)fujii(at)gmail(dot)com>
Author: Simon Riggs <simon(at)2ndquadrant(dot)com>
Author: Abhijit Menon-Sen <ams(at)2ndquadrant(dot)com>
Author: Sergei Kornilov <sk(at)zsrv(dot)org>

Уже прошло две недели и этот коммит не откатили. Удивительно. И, кажется, даже не собираются. Поразительно. Неизвестно, не решит ли сообщество поменять поведение в какую-нибудь сторону ещё раз, тем более до feature freeze релиза postgresql 12 в апреле ещё есть немного времени. Но, похоже, больше recovery.conf всё-таки у нас не будет.

Так что же изменилось

Сперва-наперво, СУБД откажется стартовать, если найдёт recovery.conf файл — это было сделано специально, чтобы пользователь воспользовавшись одной из множества старых инструкций не удивлялся, почему база игнорирует конфигурацию в этом файле.

Теперь её, равно и как сам факт наличия recovery.conf для включения режима восстановления, заменяют два файла (любого содержания, обычно пустые): Старая настройка standby_mode пропала.

  • $PGDATA/recovery.signal — идеалогический наследник standby_mode=off, восстановление из архива будет произведено до указанной в конфигах точки;
  • $PGDATA/standby.signal — соответственно, standby_mode=on. Этот файлик мы будем видеть на всех репликах

Если startup процесс базы нашёл оба файла — то считаем что мы в режиме standby.

Если для ясности свести изменения параметров в табличку:

old recovery.conf

PostgreSQL 12+ postgresql.conf

primary_conninfo

primary_conninfo

primary_slot_name

primary_slot_name

trigger_file

promote_trigger_file

recovery_min_apply_delay

recovery_min_apply_delay

recovery_target

recovery_target

recovery_target_name

recovery_target_name

recovery_target_time

recovery_target_time

recovery_target_xid

recovery_target_xid

recovery_target_lsn

recovery_target_lsn

recovery_target_inclusive

recovery_target_inclusive

recovery_target_timeline

recovery_target_timeline

recovery_target_action

recovery_target_action

restore_command

restore_command

archive_cleanup_command

archive_cleanup_command

recovery_end_command

recovery_end_command

То можно заметить, что изменено чуть меньше чем ничего. На данный момент (за единственным исключением префикса promote_ для promote_trigger_file) все новые параметры называются точно так же как и старые и принимают те же самые возможные значения. Хотя на самом деле есть ещё изменение касательно настроек цели для восстановления. Не знаю, пользовался ли этим кто-то раньше, но это было задокументированное поведение и можно было указать одновременно несколько recovery_target, recovery_target_lsn, recovery_target_name, recovery_target_time или recovery_target_xid. Например,

recovery_target_lsn = '1/1D9FEA00'
recovery_target_xid = '5238954'

Реально использовалась для восстановления последняя строка из recovery.conf. Больше так нельзя, цель для восстановления должна быть указана максимум одна. Впрочем, из-за логики инфраструктуры GUC по-прежнему можно указать одноимённый параметр несколько раз:

recovery_target_lsn = '1/1D9FEA00'
recovery_target_lsn = '1/16AC7D0'

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

pg_basebackup -R (--write-recovery-conf) остался на своём месте и делает то что и предназначен, лишь только теперь он вместо recovery.conf добавит параметры в postgresql.auto.conf и создаст файл standby.signal И, в общем-то, это всё что следует сказать об изменениях видимых снаружи PostgreSQL.

Все новые параметры по-прежнему установлены как PGC_POSTMASTER, то есть могут быть изменены только при старте PostgreSQL. К сожалению, говоря о том, что это все видимые в данный момент изменения я именно это и имею в виду. Так что сейчас PostgreSQL в замечательной стадии разработки, когда старое поведение уже сломали, а изменений к лучшему ещё не завезли. Как уже упоминалось, это было требование со стороны сообщества разработчиков: сначала перенести все настройки, и только потом уже смотреть, можно ли их менять на запущенной базе.

Посмотрим, что из этого получится. Я уже опубликовал патч который разрешит менять primary_conninfo и primary_slot_name налету.

Простите, я сломал ваш recovery.conf

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть