Уровень 3.0
Предусловия:
- Изучена лекция 4 «Протокол репликации и архив WAL»
Настройка потокового и непрерывного архивирований
Подготовка виртуальной машины Host1
-
Подключитесь к виртуальной машине посредством
webssh, указав ip-адрес Host1 . -
В терминале подключитесь в
psqlк базе данныхpostgresот имени пользователяpostgres:[student@ServerName ~]$ psql -U postgrespsql (15.5)Type "help" for help. -
Создайте роль
replicator:postgres=# CREATE ROLE replicator WITH LOGIN REPLICATION PASSWORD 'replicator';CREATE ROLEУказанная роль будет использоваться для подключения по протоколу репликации, поэтому требуется наличие атрибута
REPLICATION. -
Создайте базу данных
archive_dbи подключитесь к ней:postgres=# CREATE DATABASE archive_db;CREATE DATABASEpostgres=# \c archive_dbYou are now connected to database "archive_db" as user "postgres".
Подготовка виртуальной машины Host2
-
Подключитесь к виртуальной машине посредством
webssh, указав ip-адрес Host2. -
В домашнем каталоге пользователя
studentсоздайте каталогarchiveи перейдите в него:[student@ServerName ~]$ mkdir archive && cd archive
Настройка подключения по протоколу репликации
-
В сеансе
psqlна Host1 проверьте значения параметровwal_level,max_wal_sendersиmax_replication_slots:archive_db=# SELECT name, setting FROM pg_settings WHERE name IN ('wal_level', 'max_wal_senders', 'max_replication_slots');name | setting-----------------------+---------max_replication_slots | 10max_wal_senders | 10wal_level | replica(3 rows)Вспомним, что для возможности подключения по протоколу репликации уровень журнала (
wal_level) должен быть не менееreplica.Также должно быть достаточным допустимое количество процессов
wal sender(max_wal_senders), и в случае использования слота репликации — значение параметраmax_replication_slots.Значения по умолчанию указанных параметров позволяют использовать протокол репликации в рамках лабораторной работы.
-
В сеансе
psqlна Host1 проверьте настройки в файлеpg_hba.conf:archive_db=# SELECT line_number, type, database, user_name, address, netmask, auth_method FROM pg_hba_file_rules;line_number | type | database | user_name | address | netmask | auth_method-------------+-------+---------------+-----------+---------------+-----------------------------------------+---------------89 | local | {all} | {all} | | | trust91 | host | {all} | {all} | 172.29.53.165 | 255.255.255.255 | trust92 | host | {all} | {all} | 0.0.0.0 | 0.0.0.0 | scram-sha-25693 | host | {all} | {all} | 127.0.0.1 | 255.255.255.255 | trust95 | host | {all} | {all} | ::1 | ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff | trust98 | local | {replication} | {all} | | | trust99 | host | {replication} | {all} | 127.0.0.1 | 255.255.255.255 | trust100 | host | {replication} | {all} | ::1 | ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff | trust(8 rows)Текущие настройки
pg_hba.confне позволяют подключаться по протоколу репликации через сетевой интерфейс. Исправим это. -
В сеансе
psqlна Host1 добавьте в файлpg_hba.confразрешение для доступа через сетевой интерфейс по протоколу репликации:archive_db=# \! sudo sed -i '99i\host replication all 0.0.0.0/0 scram-sha-256' /pgdata/\{pangolin_version\}/data/pg_hba.confВ этом случае перед 99-й строкой файла
pg_hba.confбыла добавлена строка с разрешением доступа через сетевой интерфейс с аутентификацией по паролю. -
В сеансе
psqlна Host1 проверьте корректность внесенных вpg_hba.confизменений и перечитайте конфигурацию:archive_db=# SELECT line_number, type, database, user_name, address, netmask, auth_method FROM pg_hba_file_rules;line_number | type | database | user_name | address | netmask | auth_method-------------+-------+---------------+-----------+---------------+-----------------------------------------+---------------89 | local | {all} | {all} | | | trust91 | host | {all} | {all} | 172.29.53.165 | 255.255.255.255 | trust92 | host | {all} | {all} | 0.0.0.0 | 0.0.0.0 | scram-sha-25693 | host | {all} | {all} | 127.0.0.1 | 255.255.255.255 | trust95 | host | {all} | {all} | ::1 | ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff | trust98 | local | {replication} | {all} | | | trust99 | host | {replication} | {all} | 0.0.0.0 | 0.0.0.0 | scram-sha-256100 | host | {replication} | {all} | 127.0.0.1 | 255.255.255.255 | trust101 | host | {replication} | {all} | ::1 | ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff | trust(9 rows)archive_db=# SELECT pg_reload_conf();pg_reload_conf----------------t(1 row)Необходимое разрешение успешно добавлено. Для применения новых настроек файлы конфигурации были перечитаны функцией
pg_reload_conf. -
В терминале на Host2 подключитесь в
psqlк кластеру, развернутому на Host1, по протоколу репликации. При этом используйте ip-адрес, соответствующий вашей виртуальной машине Host1:student@ServerName archive]$ psql "host={replica-IP} user=replicator replication=true"Password for user replicator:psql (15.5)Type "help" for help.Вспомним, что
psqlподдерживает работу по протоколу репликации.Для этого в строке подключения было указано
replication=true. -
В сеансе
psqlна Host2 выполните одну из команд протокола репликации:replicator=> IDENTIFY_SYSTEM;systemid | timeline | xlogpos | dbname---------------------+----------+-----------+--------7558839795421325717 | 1 | 0/1DC7D78 |(1 row)Команда
IDENTIFY_SYSTEMзапрашивает идентификационные данные экземпляра сервера, в том числе идентификатор кластера баз данных (systemid) и текущую позицию записи в журнале WAL (xlogpos), с которой может начаться передача записей по протоколу репликации.Поле
timelineсодержит идентификатор текущей линии времени. Он используется при физическом резервном копировании. Его назначение станет понятным в следующей лекции.Поле
dbnameиспользуется при логической репликации для указания имени базы данных.Успешное выполнение команды
IDENTIFY_SYSTEMподтверждает подключение по протоколу репликации.В протоколе предусмотрен еще ряд команд, среди которых можно выделить команду создания слота репликации (
CREATE_REPLICATION_SLOT) и команду запуска потоковой передачи записей WAL (START_REPLICATION).Однако напрямую мы их использовать не будем. Вместо этого доверимся утилите
pg_receivewal, которая на основе протокола репликации обеспечивает архивирование записей WAL.Но для начала сверим полученное значение
xlogposс результатом функцииpg_current_wal_lsn, показывающей текущую позицию вставки журнала. -
В сеансе
psqlна Host1 проверьте текущую позицию записи журнала WAL:archive_db=# SELECT pg_current_wal_lsn();pg_current_wal_lsn--------------------0/1DC7D78(1 row)Как и ожидалось, позиции записей совпадают.
-
Выйдите из
psqlна Host2:replicator=> \q
Потоковое архивирование
-
В терминале на Host2 создайте слот репликации с использованием утилиты
pg_receivewal. При этом используйте ip-адрес, соответствующий вашей виртуальной машине Host1, а также введите пароль ролиreplicator("replicator"):[student@ServerName archive]$ pg_receivewal --create-slot --slot=archive_slot -U replicator -h 172.29.53.165Password:Утилита
pg_receivewalпозволяет создавать слоты репликации. Для этого были указаны ключ--create-slotи имя слота в ключе--slot. -
В сеансе
psqlна Host1 проверьте наличие созданного слота:archive_db=# SELECT slot_name, slot_type, active, restart_lsn FROM pg_replication_slots;slot_name | slot_type | active | restart_lsn--------------+-----------+--------+-------------archive_slot | physical | f |(1 row)Созданный слот отображается в представлении
pg_replication_slots. Однако он еще не использовался, поэтому полеrestart_lsn(LSN старейшей записи сегмента, который еще может быть нужен пользователям слота) пустое.Значение поля
activeговорит о том, что слот в текущий момент никем не используется. -
В сеансе
psqlна Host1 проверьте, какой сегмент WAL используется в текущий момент:archive_db=# SELECT pg_walfile_name(pg_current_wal_lsn());pg_walfile_name--------------------------000000010000000000000001(1 row)Пока в журнале WAL всего один сегмент, который используется для сохранения новых записей.
-
В терминале на Host2 с использованием утилиты
pg_receivewalзапустите потоковое архивирование. При этом используйте ip-адрес, соответствующий вашей виртуальной машине Host1:[student@ServerName archive]$ pg_receivewal -D ./ --slot=archive_slot -d "host={IP-Address} user=replicator password=replicator" &[1] 18853Теперь было запущено непосредственно потоковое получение записей WAL.
Это было сделано в фоновом режиме (в конце команды
&). Пароль при этом был указан непосредственно в строке подключения.Получение записей выполняется посредством созданного слота
--slot=archive_slot.Записи сохраняются в каталоге
archive(-D ./) домашнего каталога пользователяstudent. -
В терминале на Host2 проверьте содержимое текущего каталога:
[student@ServerName archive]$ ls -1000000010000000000000001.partialВ каталоге
archiveсразу был создан файл-сегмент. Расширениеpartialозначает, что он еще не заполнен полностью. -
В сеансе
psqlна Host1 создайте простую таблицу и наполните ее данными:archive_db=# CREATE TABLE some_table AS SELECT 'Потоковое архивирование!' FROM generate_series(1, 100000);SELECT 100000Вспомним, что операции массовой обработки данных попадают в журнал при его уровне не менее
replica. -
В сеансе
psqlна Host1 проверьте, какой сегмент WAL используется в текущий момент:archive_db=# SELECT pg_walfile_name(pg_current_wal_lsn());pg_walfile_name--------------------------000000010000000000000002(1 row)В этом случае первый сегмент был полностью заполнен, и было осуществлено переключение на следующий сегмент.
-
В терминале на Host2 проверьте содержимое текущего каталога:
[student@ServerName archive]$ ls -1000000010000000000000001000000010000000000000002.partialНовые записи сразу попали в архив. Первый сегмент в нем также полностью заполнен.
-
В сеансе
psqlна Host1 проверьте состояние слота репликации:archive_db=# SELECT slot_name, slot_type, active, restart_lsn FROM pg_replication_slots;slot_name | slot_type | active | restart_lsn--------------+-----------+--------+-------------archive_slot | physical | t | 0/2000000(1 row)Слот репликации теперь активен и хранит LSN первой записи (
restart_lsn) сегмента, начиная с которого контрольная точка не будет удалять накопленные сегменты.Тут стоит уточнить, что контрольная точка все же может удалять еще необходимые слотам сегменты WAL.
Право удаления контрольной точкой сегментов WAL, еще необходимых слотам репликации, возникает в случае превышения их общим размером значения параметра
max_slot_wal_keep_size. По умолчанию указанный параметр имеет значение -1, что означает отсутствие ограничения на максимальный размер сегментов WAL, необходимых для контрольных точек. -
В терминале на Host2 завершите процесс
pg_receivewal.При этом используйте
pidпроцесса, полученный при его запуске в фоне в п. 4:[student@ServerName archive]$ kill 18853[1]+ Terminated pg_receivewal -D ./ --slot=archive_slot -d "host={replica-IP} user=replicator password=replicator" -
В сеансе
psqlна Host1 проверьте состояние слота репликации:archive_db=# SELECT slot_name, slot_type, active, restart_lsn FROM pg_replication_slots;archive_db=# SELECT slot_name, slot_type, active, restart_lsn FROM pg_replication_slots;slot_name | slot_type | active | restart_lsn--------------+-----------+--------+-------------archive_slot | physical | f | 0/2000000(1 row)Теперь слот неактивен. При этом
restart_lsnне пустой.Это означает, что все сегменты начиная с
restart_lsnне будут удаляться, пока не пройдут через слот, который никем не используется.Как можно догадаться, это плохая ситуация: сегменты будут бесконечно накапливаться.
Как раз для выявления таких слотов (с целью их дальнейшего удаления) и предназначено представление
pg_replication_slots. -
В сеансе
psqlна Host1 удалите слот репликации:archive_db=# SELECT pg_drop_replication_slot('archive_slot');pg_drop_replication_slot--------------------------(1 row)archive_db=# SELECT slot_name, slot_type, active, restart_lsn FROM pg_replication_slots;slot_name | slot_type | active | restart_lsn-----------+-----------+--------+-------------(0 rows)Теперь процессу контрольной точки ничто не препятствует удалить ненужные сегменты WAL.
Непрерывное архивирование
В этом разделе все команды выполняются на виртуальной машине Host1.
-
Проверьте, включен ли режим непрерывного архивирования:
archive_db=# SHOW archive_mode;archive_mode--------------off(1 row)Вспомним, что непрерывное архивирование осуществляется самим экземпляром сервера путем выполнения команды оболочки.
По умолчанию оно выключено.
-
Включите непрерывное архивирование и укажите команду оболочки для копирования сегментов WAL:
archive_db=# ALTER SYSTEM SET archive_mode = on;ALTER SYSTEMarchive_db=# ALTER SYSTEM SET archive_command = 'test ! -f /home/postgres/archive/%f && cp %p /home/postgres/archive/%f';ALTER SYSTEMДля указания пути копируемого файла сегмента относительно каталога данных в команде используется подстановка
%p, для указания только имени файла —%f.В этом случае сначала проверяется наличие файла с названием копируемого сегмента, и только в случае его отсутствия выполняется копирование сегмента.
Проверка наличия архивного файла перед копированием сегмента с тем же именем — это распространенная мера сохранения целостности архива в случае ошибки администратора.
Она защищает от перезаписи архивных файлов, например, в случае использования одного архивного каталога для разных экземпляров сервера.
Каталог с архивом, указанный в команде, еще не создан. Создадим его.
-
Выйдите из
psqlи запустите оболочку от имени пользователяpostgres:archive_db=# \q[student@ServerName ~]$ sudo -iu postgres -
В домашнем каталоге пользователя
postgresсоздайте каталогarchiveи перейдите в него:[postgres@ServerName ~]$ mkdir ~/archive && cd ~/archiveКаталог должен принадлежать пользователю
postgres, поскольку запись в него будет осуществляться самим экземпляром, запущенным от имени пользователяpostgres. -
Перезапустите экземпляр сервера:
[postgres@ServerName archive]$ pg_ctl restart -l ~/logfilewaiting for server to shut down.... doneserver stoppedwaiting for server to start.... doneserver startedПерезапуск потребовался после изменения параметра
archive_mode. -
Подключитесь в
psqlк базе данныхarchive_db:[postgres@ServerName archive]$ psql -d archive_dbpsql (15.5)Type "help" for help. -
Проверьте, какой сегмент WAL используется в текущий момент:
archive_db=# SELECT pg_walfile_name(pg_current_wal_lsn());pg_walfile_name--------------------------000000010000000000000002(1 row)Запись по-прежнему ведется во второй сегмент.
-
Вставьте в таблицу
some_table1000 строк и посмотрите содержимое каталога~/archive:archive_db=# INSERT INTO some_table SELECT 'Непрерывное архивирование!' FROM generate_series(1,1000);INSERT 0 1000archive_db=# \! ls -1 ~/archiveПосле вставки 1000 строк архив по-прежнему пустой.
Это означает, что записи WAL поместились в текущий сегмент.
Вспомним, что копирование сегмента в ходе непрерывного архивирования выполняется при переключении на следующий сегмент.
-
Проверьте, какой сегмент WAL используется в текущий момент:
archive_db=# SELECT pg_walfile_name(pg_current_wal_lsn());pg_walfile_name--------------------------000000010000000000000002(1 row)Действительно, сегмент еще не сменился.
Инициируем его смену вручную.
-
Переключитесь вручную на следующий сегмент WAL и проверьте, какой сегмент стал использоваться после этого:
archive_db=# SELECT pg_switch_wal();pg_switch_wal---------------0/28623CA(1 row)archive_db=# SELECT pg_walfile_name(pg_current_wal_lsn());pg_walfile_name--------------------------000000010000000000000003(1 row)Теперь сегмент сменился. Предыдущий должен был быть скопирован в архив. Проверим это.
-
Посмотрите содержимое каталога
~/archive:archive_db=# \! ls -1 ~/archive000000010000000000000002Сегмент скопирован. Непрерывное архивирование настроено.
Завершение
Завершение на виртуальной машине Host1
-
Сбросьте настройки непрерывного архивирования:
archive_db=# ALTER SYSTEM RESET archive_command;ALTER SYSTEMarchive_db=# ALTER SYSTEM RESET archive_mode;ALTER SYSTEM -
Подключитесь к базе данных
postgresи удалите базу данныхarchive_db:archive_db=# \c postgresYou are now connected to database "postgres" as user "postgres".postgres=# DROP DATABASE archive_db;DROP DATABASE -
Выйдите из
psqlи перезапустите экземпляр сервера:postgres=# \q[postgres@ServerName archive]$ pg_ctl restart -l ~/logfilewaiting for server to shut down.... doneserver stoppedwaiting for server to start.... doneserver started -
Удалите каталог
archive:
[postgres@ServerName archive]$ cd ~ && rm -r archive
-
Выйдите из оболочки, выполняемой от имени пользователя
postgres:[postgres@ServerName ~]$ exitlogout
Завершение на виртуальной машине Host2
Удалите каталог archive:
[student@ServerName archive]$ cd ~ && rm -r archive
Самопроверка
Вопрос 1
В сеансе psql выполнена следующая последовательность команд:
some_db=# SHOW max_slot_wal_keep_size;
max_slot_wal_keep_size
------------------------
-1
(1 row)
some_db=# SELECT pg_ls_dir('pg_wal');
pg_ls_dir
--------------------------
archive_status
000000010000000000000001
000000010000000000000002
000000010000000000000003
000000010000000000000004
000000010000000000000005
(3 rows)
some_db=# SELECT slot_name, slot_type, active, restart_lsn FROM pg_replication_slots;
slot_name | slot_type | active | restart_lsn
--------------+-----------+--------+-------------
slot1 | physical | f | 0/3000000
slot2 | physical | f |
slot3 | physical | t | 0/4000000
(3 row)
Удалению каких сегментов WAL не препятствуют слоты репликации? Выберите все верные варианты ответа
Вопрос 2
Содержимое каталога с сегментами WAL представлено ниже:
[student@pangolin-prac-c51koi ~]$ ls -1 /wal
000000010000000000000005
000000010000000000000006
000000010000000000000007
000000010000000000000008.partial
Какое средство могло быть использовано для наполнения каталога /wal при условии, что оно было единственным и применялись стандартные правила именования сегментов WAL?
Вопрос 3
В сеансе psql выполнена следующая последовательность команд:
some_db=# SHOW archive_mode;
archive_mode
--------------
on
(1 row)
some_db=# SHOW archive_command;
archive_command
-----------------
cp %p /archive/%f
(1 row)
some_db=# SELECT pg_walfile_name(pg_current_wal_lsn());
pg_walfile_name
--------------------------
000000010000000000000004
(1 row)
Какие файлы могут находиться в каталоге /archive при условии, что создание файлов в нем выполняет только процесс archiver? Выберите все верные варианты ответа