Postgresql 12 Replication

для запуска репликации на слейве использовалась pg_basebackup. Имеем:

  1. PostgreSQL 12.18 (Ubuntu 12.18-1.pgdg22.04+1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0, 64-bit
  2. Размер бд = 2Т
  3. время выкачки с мастера на слейв более 10 часов; pg_basebackup -h 1.2.3.4 -p 5432 -D /database/postgresql12 -U sys_replication -v -P -R -X stream
  4. падение реплики после 14 часов работы; на мастере видим:
    "2024-03-19 01:57:53 MSK [4704]: user=sys_replication,db=[unknown],app=axirate- 
    postgres,client=172.31.1.37(58688)"ERROR:  requested WAL segment 000000010001CCB30000003A has 
    already been removed

на реплике в принципе тоже самое:

    "2024-03-19 01:57:53 MSK [3341706]: user=,db=,app=,client="FATAL:  could not receive data 
from WAL stream: ERROR:  requested WAL segment 000000010001CCB30000003A has already been removed
    "2024-03-19 01:57:53 MSK [3256191]: user=,db=,app=,client="LOG:  invalid magic number 0000 in 
log segment 000000010001CCB30000003A, offset 4325376
    "2024-03-19 01:57:53 MSK [3520895]: user=,db=,app=,client="LOG:  started streaming WAL from 
primary at 1CCB3/3A000000 on timeline 1
    "2024-03-19 01:57:53 MSK [3520895]: user=,db=,app=,client="FATAL:  could not receive data 
from WAL stream: ERROR:  requested WAL segment 000000010001CCB30000003A has already been removed

Утилита pg_basebackup требует наличие пустой datadir (иначе она не запуститься). Поэтому каждый раз использовать ее для закачки данных на слейв и ждать 10 - 12 часов как то не хочеться.

Архивация WAL файлов на отд. сервере не используется.

На маленьких базах протестировал метод:


    1)    pg_start_backup() on the master;
    2)    Stop the replica if running;
    3)    rsync the master to the replica (master ---> replica)
    4)    pg_stop_backup() on the master
    5)    rsync the master to the replica (master ---> replica) only pg_wal directory;
    6)    !!! Check standby.signal and check postgresql.auto.conf
    7)    Start the replica

На небольшой базе данный способ работает и реплика запустилаcь.

У меня 2 вопроса:

  1. применим ли данный способ на больших базах (2Т) ? Какие могут быть минусы?
  2. как использовать вывод команд pg_start_backup и pg_stop_backup ?

pg_stop_backup отдает:

    pg_stop_backup
    19/C8000138

который может использоваться для выкачки WAL файлов начиная с 19/C8000138. Но как сопоставить это с именем WAL-файла, например 0000000300000019000000C8 ?


Ответы (1 шт):

Автор решения: Мелкий

Чтобы ещё это потом работало стабильно, а не отваливалась репликация сразу как чуть отстанет реплика, нужно любым удобным способом обеспечить сохранение для репликации тех WAL, которые больше не нужны самому мастеру. Способы такие (несортированный список):

Архив WAL

конфигурируете на мастере archive_mode=on (требует рестарт базы для включения) и какую-то archive_command. Мастер будет вызывает эту archive_command для каждого WAL файла и вы куда-то это добро сохраняете. Потом реплика может подтягивать что ей нужно через restore_command

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

В целом архив WAL - это про бекапы и point-in-time recovery, чем про репликацию. Но если для бекапов этой базы будет нужен архив, то почему бы его и не использовать.

Слоты репликации

Делаете слот физической репликации (можно попросить pg_basebackup его создать для вас, опция --create-slot). Снимаете pg_basebackup с указанием этого слота --slot=slotname, потом запускаете реплику. Слот репликации не даст мастеру удалять те WAL, о получении которых ещё не отчиталась реплика.

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

В pg13 есть настройка max_slot_wal_keep_size, какой объём WAL может держать слоты репликации, после чего слот инвалидируется и база удалит эти WAL. Реплика соответственно не сможет продолжить репликацию (если нет архива WAL), но мастер не сложится.

Хранить фиксированный объём избыточных WAL

настройкой wal_keep_segments указываете, сколько WAL файлов базе нужно хранить, даже если они не нужны самой базе для crash recovery. Настройка измеряется числом сегментов WAL, обычно по 16мб каждый (справочная величина show wal_segment_size;). Соответственно, wal_keep_segments = 100 - 1600мб лага репликации, который реплика сможет догнать самостоятельно без приключений.

начиная с pg13 это настройка wal_keep_size и считается уже в мегабайтах, а не сегментах.

Одновременно недостаток и преимущество - это место будет занято постоянно, в отличии от слотов репликации. Отстаёт ли реплика или лага репликации нет, весь заявленный wal_keep_segments (или wal_keep_size) будет на диске занят. Преимущество в том, что если реплика начинает отставать, то у вас стабильный график места на диске, а не начинает внезапно убывать место на мастере.


применим ли данный способ на больших базах (2Т) ? Какие могут быть минусы?

это ровно то же самое, что сделает pg_basebackup -X fetch. Не взлетит без архива WAL, без него вы не обеспечите непрерывную историю WAL от pg_start_backup до момента запуска walreceiver.

как использовать вывод команд pg_start_backup и pg_stop_backup ?

прочитать в документации. Это низкоуровневый API, не предполагающий использование без понимания как база этим будет пользоваться. Чтобы им воспользоваться и получить внятный результат - прочесть и осмыслить документацию необходимо.

→ Ссылка