PostgreSQL15-增量备份

1. 增量备份概述

  • 增量备份依赖于 WAL 机制,通过持续归档 WAL 日志实现增量数据保护,并结合基础备份(全量备份)实现时间点恢复(PITR,Point-in-Time Recovery)。
  • 其核心逻辑是:基础备份提供某一时刻的完整数据快照,归档的 WAL 日志记录后续所有数据变更,通过两者结合可将数据库恢复到任意时间点。

2. WAL 日志归档配置

2.1 归档目录准备

  • 需创建用于存储 WAL 归档日志的目录,并确保 PostgreSQL 进程(通常为 postgres 用户)有读写权限
mkdir -p /pgdata/16/{backups,archive_wals}  # 分别用于基础备份和WAL归档
chown -R postgres:postgres /pgdata/16
chmod 700 /pgdata/16/archive_wals

2.2 配置 postgresql.conf

  • 注意:
  • wal_level 和 archive_mode 修改后需重启数据库生效;
  • 初期可将 archive_command 设为 '/bin/true'(仅开启归档模式但不实际归档),需正式归档时再修改为实际命令。
wal_level = replica
archive_mode = on         # 开启归档模式

# 归档命令:将WAL文件复制到归档目录(示例为压缩存储)
# %p:当前WAL文件的全路径(如pg_wal/000000010000000000000001)
# %f:当前WAL文件的文件名(如000000010000000000000001)
archive_command = 'gzip < %p > /pgdata/16/archive_wals/%f.gz'

max_wal_senders = 10     # 允许的WAL发送进程数(需≥1,支持备份和复制)
wal_keep_size = 1GB      # 额外保留的WAL大小(防止归档延迟导致的WAL被清理)

2.3 配置访问控制(pg_hba.conf)

  • 若通过远程备份工具(如 pg_basebackup)创建基础备份,需允许复制连接
  • 修改后需执行 pg_ctl reload 或 SELECT pg_reload_conf(); 生效。
# 允许本地postgres用户通过密码认证进行复制连接
local   replication     postgres     md5

# 若需远程备份,添加远程访问规则(示例)
host    replication     postgres     192.168.1.0/24     md5

3. WAL 日志归档触发机制

  • 手动切换:执行 SELECT pg_switch_wal(); 强制切换当前 WAL 文件并触发归档
    • PostgreSQL 10+ 用 pg_switch_wal()
    • 低版本为 pg_switch_xlog()
  • 文件写满:默认单个 WAL 文件大小为 16MB。写满后自动切换并归档。
    • 可通过 wal_segment_size 调整,需初始化数据库时设置
  • 时间间隔:通过 archive_timeout 参数设置(单位秒,如 archive_timeout = 300)

4. 基础备份创建(全量备份)

  • 基础备份是增量备份的基础,提供数据库在某一时刻的完整快照。PostgreSQL 16 推荐使用 pg_basebackup 工具
# 切换至postgres用户
su - postgres

# 创建基础备份(示例参数说明)
pg_basebackup \
  -h localhost \          # 数据库主机(本地可省略)
  -p 5432 \               # 端口号
  -U postgres \           # 备份用户(需有复制权限)
  -Ft \                   # 输出为tar格式
  -Pv \                   # 显示进度和详细信息
  -Xf \                   # 备份期间自动切换WAL,确保一致性(-X fetch)
  -z \                    # 压缩tar文件(gzip)
  -Z5 \                   # 压缩级别(1-9,5为平衡值)
  -D /pgdata/16/backups/base_$(date +%Y%m%d_%H%M%S).tar.gz  # 备份文件路径及名称
  • 注意:-Xf(fetch 模式)会在备份结束时获取当前 WAL 位置,确保基础备份包含截至备份完成时的所有数据;若用 -Xs(stream 模式),会实时流式传输 WAL,适合大数据库备份。

5. 增量恢复(PITR 时间点恢复)

5.1 恢复前准备

systemctl stop postgresql-16            # 停止数据库
pg_ctl stop -D /var/lib/pgsql/16/data   # 或者

# 清理或迁移原数据目录,这里选择备份原数据目录
mv /var/lib/pgsql/16/data /var/lib/pgsql/16/data_old
mkdir -p /var/lib/pgsql/16/data         # 创建新数据目录

# 恢复基础备份
tar zxf /pgdata/16/backups/base_20241001_100000.tar.gz -C /var/lib/pgsql/16/data

5.2 配置恢复参数(recovery.conf 的替代方案)

  • PostgreSQL 12 及以上版本已移除 recovery.conf,恢复参数需直接写入 postgresql.conf 或单独的配置文件(通过 include 引入),并在数据目录中创建 recovery.signal 文件触发恢复模式。

5.2.1 配置恢复命令

  • 在 postgresql.conf 中添加以下参数:
# 从归档目录恢复WAL日志的命令(需与archive_command对应,如解压)
restore_command = 'gunzip -c /pgdata/16/archive_wals/%f.gz > %p'

# 可选:设置恢复目标(默认恢复到最新状态)
# recovery_target_timeline = 'latest'  # 恢复到最新时间线(默认)

5.2.2 触发恢复模式

  • 创建 recovery.signal 文件(空文件即可),用于告诉 PostgreSQL 启动时进入恢复模式
touch /var/lib/pgsql/16/data/recovery.signal
chown postgres:postgres /var/lib/pgsql/16/data/recovery.signal

5.3 高级恢复目标设置

可通过配置参数指定恢复到特定时间点、事务或还原点,在 postgresql.conf 中添加对应参数即可:

恢复到指定时间点:
recovery_target_time = '2024-10-01 15:30:00+08' # 时间需包含时区

恢复到指定还原点:
先在源数据库创建还原点:SELECT pg_create_restore_point('my_restore_point');

恢复时指定:
recovery_target_name = 'my_restore_point'

恢复到指定事务 ID:
需先获取目标事务 ID(如 SELECT txid_current();):

recovery_target_xid = '500' # 事务ID为500

恢复到指定时间线:
时间线(Timeline)用于区分数据库分支(如恢复后再次写入会生成新时间线):

recovery_target_timeline = '2' # 恢复到时间线2
可通过 pg_controldata /var/lib/pgsql/16/data | grep Timeline 查看当前时间线。

5.4 启动数据库并完成恢复

启动数据库:
systemctl start postgresql-16

确认恢复完成:
数据库启动后会自动应用归档的 WAL 日志,直至达到恢复目标。
恢复完成后,recovery.signal 文件会被自动删除,数据库进入正常运行模式。
若需验证,可查询数据是否恢复到预期状态。

6. 备份与恢复脚本示例

6.1 自动备份脚本(pg_backup.sh)

bash
#!/bin/bash
# 每日创建基础备份并压缩
BACKUP_DIR="/pgdata/16/backups"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="${BACKUP_DIR}/base_${DATE}.tar.gz"

# 执行基础备份
pg_basebackup -h localhost -p 5432 -U postgres -Ft -Pv -Xf -z -Z5 -D "${BACKUP_FILE}"

# 保留最近30天的备份
find "${BACKUP_DIR}" -name "base_*.tar.gz" -type f -mtime +30 -delete
添加执行权限并通过 crontab 定时运行:0 2 * * * /path/to/pg_backup.sh

6.2 恢复脚本要点

# 1. 停止数据库
systemctl stop postgresql-16

# 2. 迁移原数据目录
mv /var/lib/pgsql/16/data /var/lib/pgsql/16/data_old
mkdir -p /var/lib/pgsql/16/data

# 3. 解压基础备份
tar zxf /pgdata/16/backups/base_20241001_100000.tar.gz -C /var/lib/pgsql/16/data

# 4. 配置恢复参数(写入postgresql.conf)
cat >> /var/lib/pgsql/16/data/postgresql.conf << EOF
restore_command = 'gunzip -c /pgdata/16/archive_wals/%f.gz > %p'
recovery_target_time = '2024-10-01 15:30:00+08'
EOF

# 5. 创建recovery.signal触发恢复
touch /var/lib/pgsql/16/data/recovery.signal
chown -R postgres:postgres /var/lib/pgsql/16/data

# 6. 启动数据库
systemctl start postgresql-16

7. 常见问题与注意事项

WAL 归档失败:若 archive_command 执行失败(如权限不足、磁盘满),PostgreSQL 会反复尝试,直至成功或触发 archive_failure_timeout(默认 0,永不超时)。需监控归档目录磁盘空间和日志(pg_log)中的错误信息。
复制槽与归档的关系:复制槽用于确保主库保留从库未接收的 WAL,但不替代归档功能。增量备份仍需依赖归档的 WAL 文件,复制槽仅用于逻辑 / 物理复制。
版本差异:
PostgreSQL 10+ 中,pg_xlog 目录已重命名为 pg_wal,相关函数如 pg_switch_xlog() 改为 pg_switch_wal(),pg_current_xlog_location() 改为 pg_current_wal_lsn()。
PostgreSQL 12+ 移除 recovery.conf,改用 recovery.signal 和 postgresql.conf 配置恢复参数。
权限问题:所有操作需确保 postgres 用户对数据目录、备份目录、归档目录有完整权限(通常为 700 权限),否则可能导致备份或恢复失败。
测试恢复流程:定期测试恢复流程,确保备份文件和归档日志可用,避免实际故障时无法恢复。

posted @ 2024-05-24 11:35  立勋  阅读(265)  评论(0)    收藏  举报