wiki/docs/postgresql/Репликация.md
ilyamak04 40ba9a93c4
All checks were successful
Build MkDocs / build-and-deploy (push) Successful in 19s
commit
2025-02-25 23:10:18 +03:00

278 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## Настройка репликации Master-Slave
- `apt install postgresql postgresql-contrib -y` - устанавливаем СУБД на обе машины
- `systemctl status postgresql`
### Настройка Master
```conf
# /etc/postgresql/16/main/postgresql.conf
listen_addresses = 'localhost,150.241.66.94' # 150.241.66.94 адрес ВМ, на которой slave
wal_level = replica # минимальный уровень необходимый для репликации
max_wal_senders = 5 # максимальное количество подключений для передачи WAL, максимум 5 слейвов
wal_keep_size = 1024MB
hot_standby = on # разрешаем селекты с реплики, по умолчанию нельзя
archive_mode = on # включаем архивирование WAL
archive_command = 'find /var/lib/postgresql/16/main/archive -type f -mtime +7 -delete; gzip < %p > /var/lib/postgresql/16/main/archive/%f.gz'
```
```
# /etc/postgresql/16/main/pg_hba.conf
# файл pg_hba.conf (Host-Based Authentication) управляет доступом к PostgreSQL, определяя, какие пользователи могут подключаться
# c каких IP-адресов и каким способом аутентификации
host replication replicator 192.168.1.2/32 scram-sha-256
```
Создадим роль для репликации, выполнить:
```bash
sudo -u postgres psql
```
```sql
CREATE ROLE replicator WITH REPLICATION LOGIN PASSWORD '<password>';
```
```sql
\q
```
Открыть «MASTER» базу данных, выполнить скрипт на обновление информации о настройках доступа из файла `pg_hba.conf`:
SELECT pg_reload_conf();
??? info "Сжатый WAL"
PostgreSQL не умеет автоматически разархивировать сжатые WAL-файлы.
Если WAL-логи в сжатом формате (.gz), то перед восстановлением их нужно разархивировать вручную в `restore_command`.
Если archive_command на master сжимает WAL при архивации, например:
archive_command = 'gzip < %p > /var/lib/postgresql/archive/%f.gz'
То restore_command на slave должен разархивировать WAL перед восстановлением:
restore_command = 'gunzip -c /var/lib/postgresql/archive/%f.gz > %p'
Как это работает?
restore_command ищет запрашиваемый WAL-файл в архиве.
Если он найден в сжатом виде (.gz), команда gunzip -c разархивирует его в нужное место (%p).
slave применяет этот WAL-файл и продолжает репликацию.
### Настройка Slave
По умолчанию реплику (slave) нельзя записывать данные, потому что она работает в режиме только для чтения (read-only), на то она и слейв реплика.
```bash
sudo systemctl stop postgresql
```
```bash
sudo -u postgres rm -rf /var/lib/postgresql/16/main/*
```
```bash
sudo -u postgres pg_basebackup -h 192.109.139.92 -U replicator -D /var/lib/postgresql/16/main -P -R --wal-method=stream` # 192.109.139.92 - ip мастера
```
Если файл standby.signal присутствует в директории данных ($PGDATA) при запуске PostgreSQL, сервер не будет принимать записи и будет получать данные с Master.
Он создаётся автоматически при запуске pg_basebackup с флагом -R или вручную.
Если удалить standby.signal и перезапустить PostgreSQL, сервер станет обычным Master (потеряет связь с репликой).
После выполнения pg_basebackup в `/var/lib/postgresql/16/main/` на Slave должен появиться файл standby.signal. Он сообщает PostgreSQL, что сервер работает как Standby (slave).
```bash
sudo systemctl start postgresql
```
```bash
sudo systemctl status postgresql
```
```sql
# проверить репликацию на мастере
SELECT * FROM pg_stat_replication;
```
```sql
# проверить репликацию на слейве
SELECT * FROM pg_stat_wal_receiver;
```
На slave после окончания загрузки бд и запуска postgres проверить наличие файла `/var/lib/pgsql/16/data/standby.signal`, а также наличие строки подключения к серверу master в файле `/var/lib/pgsql/16/data/postgresql.auto.conf`
Открыть master базу данных, выполнить скрипт на проверку состояния репликации (скрипт должен вернуть строку, в поле «state» должно быть значение «streaming»)
```sql
select * from pg_stat_replication;
```
Открыть slave базу данных, выполнить скрипт на проверку состояния репликации (скрипт должен вернуть строку, в поле «status» должно быть значение «streaming»)
```sql
select * from pg_stat_wal_receiver;
```
## Бэкапирование
По умолчанию pg_dump создает логический бэкап в формате plain (обычный SQL-скрипт)
В PostgreSQL есть два типа дампов:
- `Физические (pg_basebackup)` — побайтовая копия файлов БД.
- `Логические (pg_dump, pg_dumpall)` — SQL-скрипты или архивные файлы.
!!! info ""
`pg_dumpall` создает резервную копию всех баз данных, роли (пользователи и группы), права доступа (GRANT/REVOKE), настройки tablespace, глобальные параметры (например, настройки аутентификации). Умеет отдавать только дамп в формате .sql
`pg_dump` не экспортирует роли, права доступа, tablespaces, параметры кластера (например, `pg_hba.conf`)
1. plain (Текстовый SQL-скрипт)
Описание:
В этом формате по дефолту снимает `pg_dump`. Формат plain представляет собой обычный SQL-скрипт, содержащий скрипты `CREATE TABLE`, `INSERT INTO`, `ALTER TABLE` и другие скрипты для создания и наполнения бд .
Дамп в формате `plain`:
```bash
pg_dump -U postgres -d mydatabase -Fp -f backup.sql
```
Пример содержимого файла дампа:
```sql
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name TEXT
);
INSERT INTO users (id, name) VALUES (1, 'Alice');
```
- Можно редактировать в текстовом редакторе.
- Можно восстановить частично, скопировав нужные команды.
- Относительно долгое восстановление, так как все данные вставляются скриптами.
Как восстановить:
```bash
psql -U postgres -d mydatabase -f backup.sql
```
2. custom (Сжатый бинарный формат)
Описание:
Формат custom является бинарным, поддерживает сжатие и позволяет восстанавливать отдельные объекты базы данных, такие как таблицы и схемы.
Как создать дамп в формате `custom`:
```bash
pg_dump -U postgres -d mydatabase -Fc -Z 9 -f backup.dump
```
Параметры:
- `Fc` - указывает на использование формата custom.
- `Z 9` - применяет максимальное сжатие дампа.
- `-a` или `--data-only`: Дамп только данных, без схемы
- `-s` или `--schema-only`: Дамп только схемы, без данных
- `-O` или `--no-owner`: Исключает команды SET OWNER из дампа
- `-x` или `--no-privileges`: Исключает команды GRANT/REVOKE из дампа.
- Поддерживает выборочное снятие отдельных объектов.
- Поддерживает параллельное снятие с `-j`.
Посмотреть содержимое дампа без восстановления:
```bash
pg_restore -l backup.dump
```
Как восстановить базу данных:
```bash
pg_restore -U postgres -d mydatabase -f backup.dump
```
3. directory (Каталог с дампом)
Описание:
Формат `directory` сохраняет резервную копию в виде каталога, содержащего отдельные файлы для каждой таблицы и других объектов базы данных. Этот формат позволяет параллельно снимать бэкап.
Дамп в формате `directory`:
```bash
pg_dump -U postgres -d mydatabase -Fd -j4 -f backup_dir/
```
Параметры:
- `Fd` — указывает на формат directory.
- `j4` — использует 4 параллельных потока для ускорения процесса.
- Можно восстанавливать отдельные таблицы и объекты.
Восстановление
```bash
pg_restore -U postgres -d mydatabase -j 4 backup_dir/
```
4. tar (Архив tar)
Описание:
Формат tar создает архив tar, содержащий все необходимые файлы для восстановления базы данных. Он удобен для хранения и передачи, но восстановление в данном формате выполняется медленнее по сравнению с `directory` или `custom`.
Дамп в формате `tar`:
```bash
pg_dump -U postgres -d mydatabase -F t -f backup.tar
```
Параметры:
- Ft — указывает на формат tar.
- Медленное восстановление, так как данные сначала извлекаются из архива.
Восстановление бд:
```bash
pg_restore -U postgres -d mydatabase -Ft backup.tar
```
!!! info ""
Все форматы дампов кроме `.sql` восстанавливаются через `pg_restore`
### Пример организации бэкапирования
Скрипт `backup.sh` для снятия бэкапа, удаления бэкапов
```bash
#!/bin/bash
if [ "$#" -ne 3 ]; then
echo "Необходимо передать три аргумента."
echo "Пример: $0 <имя_стенда> <имя_базы_данных> <время_жизни_бэкапа_в_днях>"
exit 1
fi
PG_PASSWORD="postgres"
PG_PORT="5432"
STAND_NAME="$1"
DB_NAME="$2"
BACKUP_TTL="$3"
BACKUP_DIR="/opt/backups/${STAND_NAME}"
BACKUP_FILE="${STAND_NAME}_$(date +%Y%m%d).dump"
LOG_DIR="${BACKUP_DIR}/logs"
LOG_FILE="${LOG_DIR}/backup_${STAND_NAME}.log"
mkdir -p "${BACKUP_DIR}"
mkdir -p "${LOG_DIR}"
echo "$(date +%Y%m%d_%H%M%S) Начало резервного копирования базы данных ${DB_NAME}" >> ${LOG_FILE}
PGPASSWORD=${PG_PASSWORD} pg_dump -p ${PG_PORT} -h localhost -U postgres -d ${DB_NAME} -Fc -Z 9 -f "${BACKUP_DIR}/${BACKUP_FILE}" 2>> ${LOG_FILE}
if [ $? -eq 0 ]; then
echo "$(date +%Y%m%d_%H%M%S) Резервное копирование успешно завершено: ${BACKUP_DIR}/${BACKUP_FILE}" >> ${LOG_FILE}
find ${BACKUP_DIR} -type f -name "*.dump" -mtime +${BACKUP_TTL} -exec rm {} \;
if [ $? -eq 0 ]; then
echo "$(date +%Y%m%d_%H%M%S) Бэкапы старше ${BACKUP_TTL} дней удалены." >> ${LOG_FILE}
else
echo "$(date +%Y%m%d_%H%M%S) Ошибка при удалении бэкапов." >> ${LOG_FILE}
fi
else
echo "$(date +%Y%m%d_%H%M%S) Ошибка при резервном копировании базы данных ${DB_NAME}" >> ${LOG_FILE}
fi
```
Добавить в `cron`
```bash
# Для снятия бэкапа: <путь к скрипту> <имя каталога для бэкапа> <имя базы данных стенда> <кол-во хранимых бэкапов>
00 23 * * * /opt/backups/backup.sh stand1 database1 3
59 23 * * * /opt/backups/backup.sh stand2 database2 3
```