Перейти к основному содержимому

Задание 1: Настройка проверки записей WAL

В этом задании мы изучим журнал предзаписи (WAL), разберем механизмы его защиты, рассмотрим доступные режимы проверки целостности и настроим соответствующие параметры конфигурации.

Журнал предзаписи​

Вся работа со страницами данных осуществляется посредством кеша буферов, который располагается в ОЗУ. Если кеш буферов не защитить, то его содержимое, включая измененные страницы, будет утрачено в результате отключения питания или сбоя.

Защита кеша буферов реализована с помощью журнала предзаписи WAL (Write Ahead Log), в который помещаются записи с информацией о намерениях выполнить какие-либо изменения, затрагивающие данные. Записи журнала WAL должны быть помещены на энергонезависимое хранилище (диск) до того, как в кеше буферов или статусе транзакций будут произведены изменения. Если происходит сбой, то при старте СУБД записи WAL считываются и выполняются. То есть, выполняются те изменения в данных, которые были запланированы.

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

Целостность записей WAL критически важна для обеспечения возможности выполнения этих записей при запуске системы после сбоя. Поэтому все записи WAL защищены контрольными суммами.

При физической репликации записи WAL передаются с основного узла (лидера) на реплику, которая находится в процессе непрерывного восстановления. То есть, реплика непрерывно выполняет полученные с мастера записи WAL, самостоятельно изменяя данные в соответствии с полученными записями WAL.

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

postgres=# \dconfig synchronous_commit
Список параметров конфигурации
Параметр | Значение
--------------------+----------
synchronous_commit | on
(1 строка)

Установка параметра synchronous_commit = on определяет приоритет сброса данных журнала предзаписи из буфера на диск при фиксации транзакции.

Синхронная репликация включается при этом лишь тогда, когда сконфигурирован список имен реплик с помощью параметра synchronous_standby_names. Другие возможные настройки параметра synchronous_commit для синхронной репликации смотрите в документации: Write Ahead Log.

Проверить, работает ли репликация в синхронном режиме, можно следующим образом:

postgres=# SELECT * FROM pg_stat_replication \gx
-[ RECORD 1 ]----+------------------------------
pid | 110732
usesysid | 16384
usename | patroni
application_name | <IP-Address2>
client_addr | <IP-Address2>
client_hostname |
client_port | 45276
backend_start | 2026-09-18 16:00:26.069618+03
backend_xmin |
state | streaming
sent_lsn | 0/7000000
write_lsn | 0/7000000
flush_lsn | 0/7000000
replay_lsn | 0/7000000
write_lag |
flush_lag |
replay_lag |
sync_priority | 1
sync_state | sync
reply_time | 2026-09-21 15:26:47.737262+03

Поле sync_state показывает, что репликация выполняется в синхронном режиме.

Список имен реплик:

postgres=# \dconfig synchronous_standby_names
List of configuration parameters
Parameter | Value
---------------------------+-----------------
synchronous_standby_names | "<IP-Address2>"
(1 row)

Если параметр synchronous_commit выключен, то репликация происходит в асинхронном режиме и синхронизация кеша WAL с сегментами журнала предзаписи происходит периодически с помощью процесса walwriter. Периодичность синхронизации кеша WAL с диском задается настройкой:

postgres=# \dconfig wal_writer_delay
Список параметров конфигурации
Параметр | Значение
------------------+----------
wal_writer_delay | 200ms
(1 строка)

Если в режиме synchronous_commit = off произойдет сбой между сбросами кеша WAL на диск, то изменения транзакций, зафиксированные между сбросами WAL, безвозвратно пропадут и целостность данных будет нарушена.

При потоковой репликации происходит следующее (в общем случае):

  1. Мастер сервер добавляет запись WAL в сегмент журнала предзаписи на диске.
  2. Процесс walsender на мастере считывает эту запись из сегмента и передает ее реплике по сетевому протоколу репликации.
  3. На реплике процесс walreceiver получает по протоколу репликации запись WAL и добавляет ее в файл сегмента журнала.
  4. Так как реплика работает в состоянии постоянного восстановления, процесс startup считывает из файла сегмента полученную запись WAL и применяет ее.

Пример процессов на мастере:

[student@srv1 ~]$ ps f -C postgres
PID TTY STAT TIME COMMAND
110710 ? S 0:43 /usr/pangolin-6.7/bin/postgres -D /pgdata/06/data/ --config-file=/pgdata/06/data/postgresql.conf --listen_addresses=0.0.0.0 --port=5433 --cluster_name=Pobeda --wal_level
110713 ? Ss 0:00 \_ postgres: Pobeda: logger
110714 ? Ss 0:00 \_ postgres: Pobeda: checkpointer
110715 ? Ss 0:16 \_ postgres: Pobeda: background writer
110717 ? Ss 0:00 \_ postgres: Pobeda: idle sessions terminator
110718 ? Ss 0:02 \_ postgres: Pobeda: walwriter
110719 ? Ss 0:34 \_ postgres: Pobeda: autovacuum launcher
110720 ? Ss 0:00 \_ postgres: Pobeda: integrity check launcher
110721 ? Ss 0:00 \_ postgres: Pobeda: license checker
110722 ? Ss 3:22 \_ postgres: Pobeda: authproc
110723 ? Ss 0:01 \_ postgres: Pobeda: password policy cache
110724 ? Ss 0:09 \_ postgres: Pobeda: pg_cron launcher
110725 ? Ss 0:00 \_ postgres: Pobeda: logical replication launcher
110730 ? Ss 0:42 \_ postgres: Pobeda: patroni postgres 127.0.0.1(49706) idle
110732 ? Ss 1:15 \_ postgres: Pobeda: walsender patroni <IP-Address2>(45276) streaming 0/7000000

В списке процессов последний – процесс walsender.

Процессы на реплике:

[student@srv1 ~]$ ssh srv2 ps f -C postgres
PID TTY STAT TIME COMMAND
72590 ? S 0:00 /usr/pangolin-6.7/bin/postgres -D /pgdata/06/data/ --config-file=/pgdata/06/data/postgresql.conf --listen_addresses=0.0.0.0 --port=5433 --cluster_name=Pobeda --wal_level=replica --hot_standby=on --max_connections=110 --max_wal_senders=10 --max_prepared_transactions=6 --max_locks_per_transaction=64 --track_commit_timestamp=False --max_replication_slots=10 --max_worker_processes=32 --wal_log_hints=True --authentication_max_workers=16 --enable_page_compression=off
72593 ? Ss 0:00 \_ postgres: Pobeda: logger
72594 ? Ss 0:00 \_ postgres: Pobeda: checkpointer
72595 ? Ss 0:09 \_ postgres: Pobeda: background writer
72596 ? Ss 0:01 \_ postgres: Pobeda: startup recovering 000000020000000000000006
72597 ? Ss 0:00 \_ postgres: Pobeda: idle sessions terminator
72598 ? Ss 3:23 \_ postgres: Pobeda: walreceiver streaming 0/7000000
72599 ? Ss 0:00 \_ postgres: Pobeda: integrity check launcher
72600 ? Ss 0:00 \_ postgres: Pobeda: license checker
72601 ? Ss 2:17 \_ postgres: Pobeda: authproc
72602 ? Ss 0:00 \_ postgres: Pobeda: password policy cache
72607 ? Ss 0:20 \_ postgres: Pobeda: patroni postgres 127.0.0.1(35432) idle

В примере процесс с PID 72598 – walreceiver, а процесс с PID 72596 – startup.

Защита WAL​

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

Как уже говорилось, все записи WAL защищены контрольными суммами:

  • при помещении записи WAL в файл журнала предзаписи вычисляется контрольная сумма и добавляется к записи;
  • контрольная сумма проверяется при считывании записи WAL процессом восстановления startup.

Если процесс startup сталкивается с поврежденной записью WAL, он приостанавливает свою работу. Процесс репликации при этом тоже, естественно, прекращается. То есть, проверка контрольной суммы не позволяет выполнить запись WAL, если эта запись была повреждена.

Повредить запись WAL можно при:

  • операциях ввода-вывода;
  • нахождении ее в файле сегмента журнала предзаписи.

К этому, например, могут привести:

  • неисправности файловой системы;
  • сбои подсистемы ввода-вывода;
  • неисправности систем хранения данных;
  • сбои сетевых систем хранения SAN (Storage Area Network);
  • проблемы с сетевыми файловыми системами NAS (Network Attached Storage).

Для предотвращения потери записей WAL в результате их порчи в СУБД Pangolin имеется специальное решение – контроль целостности передачи WAL на реплику. Это решение основано на создании и хранении резервных копий сегментов WAL.

Сегменты WAL представляют собой файлы фиксированного размера 16Мб (по умолчанию):

postgres=# SELECT * FROM pg_ls_waldir() LIMIT 10;
name | size | modification
--------------------------+----------+------------------------
000000010000000000000001 | 16777216 | 2026-09-18 15:49:50+03
000000020000000000000001 | 16777216 | 2026-09-18 15:50:24+03
00000002.history | 41 | 2026-09-18 15:49:55+03
000000020000000000000002 | 16777216 | 2026-09-18 15:50:24+03
000000020000000000000003 | 16777216 | 2026-09-18 15:53:24+03
000000020000000000000004 | 16777216 | 2026-09-18 15:59:33+03
000000020000000000000005 | 16777216 | 2026-09-18 16:03:22+03
000000020000000000000006 | 16777216 | 2026-09-18 16:30:23+03
(8 rows)

Защита этих файлов в СУБД Pangolin построена следующим образом: запускается специальный процесс walrecoverywriter, который получает блоки для записи копии WAL-сегмента и асинхронно записывает их в файл резервной копии. К названию файла добавляется суффикс backup.

При включенной защите WAL процесс репликации осуществляется следующим образом:

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

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

Режимы проверки целостности WAL​

Проверка целостности WAL может осуществляться в Pangolin в трех разных режимах:

  • проверка контрольных сумм читаемых блоков;
  • проверка корректности данных декодированием;
  • гибридная проверка.

Проверка контрольных сумм читаемых блоков​

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

Проверка корректности данных путем декодирования​

Этот режим предусматривает декодирование записей WAL. После декодирования появляется возможность проверить как контрольную сумму, так и корректность заголовка записи WAL. В этом режиме требуется большой объем временных буферов, используемых для проверки. Если используется защитное преобразование данных, то перед декодированием необходимо рассекречивание данных.

Гибридная проверка​

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

Настройки защиты WAL​

Защита WAL настраивается с помощью следующих параметров конфигурации:

postgres=# SELECT name, setting, context FROM pg_settings WHERE name ~ '^wal_sender_[^t]';
name | setting | context
-------------------------------+---------+------------
wal_sender_backup_directory | | postmaster
wal_sender_backup_strict | off | postmaster
wal_sender_check_crc | off | postmaster
wal_sender_check_type | record | postmaster
wal_sender_panic_on_crc_error | off | postmaster
(5 rows)

Контекст всех этих параметров показывает, что при их изменении требуется перезагрузка экземпляра.

Предназначение параметров:

  • wal_sender_check_crc – включает контроль целостности WAL;
  • wal_sender_panic_on_crc_error – генерировать сообщение уровня PANIC при невозможности восстановления поврежденной записи WAL;
  • wal_sender_check_type – метод проверки WAL;
  • wal_sender_backup_directory – каталог для размещения резервных сегментов WAL и файлов с контрольными суммами;
  • wal_sender_backup_strict – задает действия при недоступности каталога.

Подведем итоги​

Вопрос 1

Вопрос 1: Посмотрите на приведенную ниже информацию:

student=> SELECT * FROM pg_stat_replication \gx
-[ RECORD 1 ]----+------------------------------
pid              | 68056
usesysid         | 16384
usename          | patroni
application_name | srv2
client_addr      | <IP-Address2>
client_hostname  | 
client_port      | 42370
backend_start    | 2026-04-27 09:07:13.955924+03
backend_xmin     | 
state            | streaming
sent_lsn         | 0/6569A30
write_lsn        | 0/6569A30
flush_lsn        | 0/6569A30
replay_lsn       | 0/6569A30
write_lag        | 
flush_lag        | 
replay_lag       | 
sync_priority    | 1
sync_state       | sync
reply_time       | 2026-05-03 19:20:35.379953+03

Какое значение имеет параметр synchronous_standby_names?

Вопрос 2

Вопрос 2: В каких режимах может работать проверка целостности WAL в Pangolin? (выберите все верные ответы)