ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

PostgreSQL故障恢复利器pg_rewind实战指南

PostgreSQL故障恢复利器pg_rewind实战指南

1. 理解pg_rewind的核心价值

当PostgreSQL主库突然宕机且备库已经接替成为新主库后,传统做法是重建整个备库——这个过程可能耗费数小时甚至数天。pg_rewind的出现彻底改变了这种局面,它能够像时光机一样,将旧主库"回退"到与新主库一致的状态,通常只需几分钟。

这个工具的核心原理是通过对比两个节点的WAL(预写式日志)差异,仅同步变更过的数据块。与rsync等全量同步工具不同,pg_rewind能智能识别哪些数据块在分歧后被修改过。在PostgreSQL 12中,这项功能得到显著增强,新增了对--write-recovery-conf参数的支持,使故障切换后的配置更加自动化。

2. 环境准备与前置条件

2.1 版本兼容性检查

pg_rewind要求主备库必须运行相同主版本的PostgreSQL(如都是12.x)。通过以下命令验证:

pg_rewind --version psql -c "SELECT version();"

2.2 关键参数配置

在postgresql.conf中必须启用以下参数:

wal_level = replica # 必须≥replica full_page_writes = on # 崩溃恢复必需 track_commit_timestamp = on # PG 12新增支持

注意:修改配置后需要重启实例生效。生产环境建议提前规划维护窗口。

2.3 数据目录权限设置

确保运行pg_rewind的操作系统用户对数据目录有写权限:

chmod 700 /var/lib/postgresql/12/main chown -R postgres:postgres /var/lib/postgresql

3. 实战演练:主备切换与重同步

3.1 模拟主库故障场景

  1. 在主库创建测试数据:
CREATE TABLE test_rewind AS SELECT generate_series(1,1000000) AS id;
  1. 强制停止主库模拟崩溃:
pg_ctl -D /var/lib/postgresql/12/main stop -m immediate
  1. 提升备库为新主库:
SELECT pg_promote();

3.2 执行pg_rewind操作

在原主库服务器执行:

pg_rewind \ --target-pgdata=/var/lib/postgresql/12/main \ --source-server="host=new_primary dbname=postgres user=postgres" \ --write-recovery-conf

关键参数解析:

  • --target-pgdata:待修复的旧主库数据目录
  • --source-server:新主库连接字符串
  • --write-recovery-conf:自动生成recovery.conf(PG 12新特性)

3.3 验证与恢复服务

  1. 检查rewind日志:
cat /var/lib/postgresql/12/main/pg_rewind.log
  1. 启动修复后的实例:
pg_ctl -D /var/lib/postgresql/12/main start
  1. 验证数据一致性:
SELECT count(*) FROM test_rewind;

4. 高级应用场景与技巧

4.1 网络隔离环境处理

当节点间无法直接连接时,可先备份新主库的WAL:

pg_basebackup -h new_primary -U postgres -D ./backup -Fp -Xs -P

然后使用本地模式rewind:

pg_rewind --target-pgdata=/old/primary --source-pgdata=./backup

4.2 大库优化参数

对于TB级数据库,建议增加:

pg_rewind --progress --buffer-size=8192 ...
  • --progress:显示实时进度
  • --buffer-size:增大I/O缓冲区(单位MB)

4.3 自动化脚本示例

#!/bin/bash PRIMARY_CONN="host=10.0.0.2 user=replicator" TARGET_DIR="/var/lib/postgresql/12/main" if pg_rewind --dry-run --target-pgdata=$TARGET_DIR --source-server="$PRIMARY_CONN"; then pg_rewind --target-pgdata=$TARGET_DIR --source-server="$PRIMARY_CONN" \ --write-recovery-conf pg_ctl -D $TARGET_DIR start else echo "Rewind not possible, need full base backup" pg_basebackup -h 10.0.0.2 -U replicator -D $TARGET_DIR -Fp -Xs -P -R fi

5. 故障排查与性能优化

5.1 常见错误解决方案

错误信息原因分析解决方案
"target server must be shut down"目标库未关闭执行pg_ctl stop -m fast
"could not find common ancestor"WAL日志不连续检查wal_keep_segments参数
"permission denied"目录权限不足设置700权限并属主为postgres

5.2 性能监控指标

通过pg_stat_progress_basebackup视图监控:

SELECT * FROM pg_stat_progress_basebackup WHERE pid = pg_backend_pid();

关键指标说明:

  • backup_streamed:已传输字节数
  • backup_total:总需传输字节数
  • tablespaces_streamed:已处理表空间数

5.3 WAL归档配置建议

在postgresql.conf中添加:

wal_keep_segments = 100 # 保留至少100个WAL段 archive_mode = on # 启用归档 archive_command = 'test ! -f /mnt/wal_archive/%f && cp %p /mnt/wal_archive/%f'

6. 生产环境最佳实践

  1. 定期验证机制:每月执行一次模拟rewind测试,确保灾难恢复流程可靠

  2. 监控关键指标:

    • pg_stat_replication.sync_state
    • pg_stat_archiver.last_failed_wal
  3. 容量规划建议:

    • 保留至少20%的磁盘空间用于rewind临时文件
    • 网络带宽应满足每小时传输1TB数据的能力
  4. 安全加固措施:

    CREATE ROLE rewind_user WITH LOGIN REPLICATION; ALTER SYSTEM SET primary_conninfo = 'user=rewind_user password=securepass';

我在实际运维中总结出一个经验公式来预估rewind时间:

预估时间(分钟) = 数据库大小(GB) × 0.05 + 未同步WAL数量 × 0.1

例如500GB数据库有100个未同步WAL文件,预计需要约35分钟完成rewind。这个经验值基于SSD存储和千兆网络环境,实际时间可能因硬件配置有所不同。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进