外观
PostgreSQL 完全恢复
核心概念
完全恢复是指将数据库恢复到最新状态,包括所有已提交的事务。在PostgreSQL中,完全恢复通常基于以下技术:
- 基础备份:数据库的完整副本,作为恢复的起点
- WAL(Write-Ahead Log)归档:记录所有数据库修改操作的日志文件
- 恢复模式:PostgreSQL的恢复模式,用于应用WAL日志
- recovery.signal:用于启动恢复模式的信号文件
完全恢复的主要特点:
- 恢复后数据库包含所有已提交的事务
- 恢复过程中会应用所有可用的WAL日志
- 恢复完成后数据库可以正常使用
- 支持多种恢复场景,包括灾难恢复、系统迁移等
完全恢复方法
1. 基于基础备份+WAL归档的恢复
这是最常用的完全恢复方法,适用于大多数恢复场景:
恢复步骤
bash
# 1. 停止PostgreSQL服务
pg_ctl stop -D /var/lib/postgresql/15/main
# 2. 清理数据目录(注意:这会删除所有现有数据)
rm -rf /var/lib/postgresql/15/main/*
# 3. 恢复基础备份
pg_basebackup -h backup_server -U replication -D /var/lib/postgresql/15/main -F t -z -X fetch -R
# 或者从本地备份恢复
rsync -a /pg_backups/base/20230101_120000/ /var/lib/postgresql/15/main/
# 4. 配置恢复参数
cat > /var/lib/postgresql/15/main/recovery.signal << EOF
# 恢复命令:从WAL归档目录恢复WAL文件
restore_command = 'cp /pg_backups/wal/%f %p'
# 恢复到最新状态(完全恢复)
# 注意:不要设置recovery_target_time或recovery_target_xid
EOF
# 5. 启动PostgreSQL服务
pg_ctl start -D /var/lib/postgresql/15/main
# 6. 验证恢复结果
psql -h localhost -U postgres -c "SELECT now();"
psql -h localhost -U postgres -c "SELECT * FROM pg_stat_wal_receiver;" # 如果是主从复制2. 基于流复制的恢复
适用于主从复制环境,当主库故障时,可以将从库提升为主库:
恢复步骤
bash
# 1. 在从库上停止PostgreSQL服务
pg_ctl stop -D /var/lib/postgresql/15/main
# 2. 检查从库状态
pg_controldata /var/lib/postgresql/15/main | grep -i state
# 3. 将从库提升为主库
pg_ctl promote -D /var/lib/postgresql/15/main
# 4. 启动PostgreSQL服务
pg_ctl start -D /var/lib/postgresql/15/main
# 5. 验证提升结果
psql -h localhost -U postgres -c "SELECT pg_is_in_recovery();" # 应返回f
psql -h localhost -U postgres -c "SELECT * FROM pg_stat_replication;" # 如果有其他从库,应显示连接3. 基于pg_restore的逻辑恢复
适用于逻辑备份的恢复,通常用于选择性恢复或跨版本迁移:
恢复步骤
bash
# 1. 创建目标数据库
createdb -h localhost -U postgres mydb
# 2. 恢复逻辑备份(完全恢复)
pg_restore -h localhost -U postgres -d mydb -j 4 /pg_backups/mydb_backup.dump
# 3. 验证恢复结果
psql -h localhost -U postgres -d mydb -c "SELECT COUNT(*) FROM pg_tables WHERE schemaname = 'public';"不同场景下的完全恢复
1. 灾难恢复
当生产数据库完全损坏时,使用完全恢复恢复数据库:
bash
# 1. 准备新的服务器
# 安装相同版本的PostgreSQL
# 配置相同的参数
# 2. 恢复基础备份
pg_basebackup -h backup_server -U replication -D /var/lib/postgresql/15/main -F t -z -X fetch -R
# 3. 配置恢复参数
cat > /var/lib/postgresql/15/main/recovery.signal << EOF
restore_command = 'scp backup_server:/pg_backups/wal/%f %p'
EOF
# 4. 启动PostgreSQL服务
pg_ctl start -D /var/lib/postgresql/15/main
# 5. 验证数据完整性
psql -h localhost -U postgres -c "SELECT * FROM critical_table LIMIT 10;"2. 系统迁移
将数据库从旧服务器迁移到新服务器:
bash
# 1. 在旧服务器上创建基础备份
pg_basebackup -h old_server -U replication -D - -F t -z | ssh new_server "cat > /pg_backups/base/migration_backup.tar.gz"
# 2. 在新服务器上恢复基础备份
mkdir -p /var/lib/postgresql/15/main
tar -xzf /pg_backups/base/migration_backup.tar.gz -C /var/lib/postgresql/15/main/
# 3. 配置恢复参数
cat > /var/lib/postgresql/15/main/recovery.signal << EOF
restore_command = 'scp old_server:/pg_backups/wal/%f %p'
EOF
# 4. 启动PostgreSQL服务
pg_ctl start -D /var/lib/postgresql/15/main
# 5. 切换应用连接到新服务器
# 更新应用配置中的数据库连接信息3. 版本升级
从旧版本PostgreSQL升级到新版本:
bash
# 1. 在旧版本服务器上创建逻辑备份
pg_dump -h old_server -U postgres -d mydb -F c -f /pg_backups/migration/mydb_backup.dump
# 2. 在新版本服务器上创建数据库
createdb -h new_server -U postgres mydb
# 3. 恢复逻辑备份(完全恢复)
pg_restore -h new_server -U postgres -d mydb -j 4 /pg_backups/migration/mydb_backup.dump
# 4. 验证恢复结果
psql -h new_server -U postgres -d mydb -c "SELECT version();"
psql -h new_server -U postgres -d mydb -c "SELECT * FROM critical_table LIMIT 10;"完全恢复最佳实践
1. 恢复前准备
- 备份验证:在恢复前验证备份文件的完整性
- 环境准备:确保目标环境与源环境配置相似
- 恢复计划:制定详细的恢复计划,包括步骤、时间和验证标准
- 权限准备:确保恢复用户具有足够的权限
2. 恢复过程优化
bash
# 优化恢复速度的配置
cat > /var/lib/postgresql/15/main/postgresql.conf << EOF
# 恢复过程中禁用autovacuum
autovacuum = off
# 增加检查点间隔
checkpoint_timeout = 30min
max_wal_size = 4GB
# 增加维护工作内存
maintenance_work_mem = 2GB
# 并行恢复设置
max_parallel_workers_per_gather = 0
max_worker_processes = 8
EOF3. 恢复后验证
bash
# 1. 检查数据库状态
psql -h localhost -U postgres -c "SELECT pg_is_in_recovery();" # 应返回f
# 2. 验证数据完整性
psql -h localhost -U postgres -c "SELECT COUNT(*) FROM critical_table;" # 与预期一致
# 3. 验证功能正常
psql -h localhost -U postgres -d mydb -c "SELECT * FROM get_report();" # 执行关键业务函数
# 4. 检查日志文件
cat /var/log/postgresql/postgresql-15-main.log | grep -i error # 无错误
# 5. 更新统计信息
psql -h localhost -U postgres -c "ANALYZE VERBOSE;"4. 恢复监控
bash
# 监控恢复进度
psql -h localhost -U postgres -c "SELECT * FROM pg_stat_wal_receiver;" # 流复制恢复
# 查看恢复状态
psql -h localhost -U postgres -c "SELECT * FROM pg_stat_progress_recovery;" # PostgreSQL 10+
# 监控恢复日志
tail -f /var/log/postgresql/postgresql-15-main.log | grep -i recovery常见问题(FAQ)
Q1:如何验证WAL归档是否完整?
A1:
bash
# 检查WAL归档目录中的文件数量
ls -la /pg_backups/wal/ | grep -i "^-" | wc -l
# 检查最近的WAL文件是否存在
ls -la /pg_backups/wal/ | sort -k 9 | tail -5
# 使用pg_waldump验证WAL文件完整性
pg_waldump /pg_backups/wal/000000010000000000000001Q2:完全恢复需要多长时间?
A2:恢复时间取决于以下因素:
- 基础备份的大小
- WAL日志的数量
- 恢复服务器的性能
- 存储I/O速度
一般来说:
- 小型数据库(< 100GB):几分钟到几小时
- 中型数据库(100GB-1TB):几小时到一天
- 大型数据库(> 1TB):一天以上
Q3:如何加速完全恢复过程?
A3:
bash
# 1. 使用并行恢复
pg_restore -j 8 -d mydb /pg_backups/mydb_backup.dump
# 2. 优化恢复配置
cat >> /var/lib/postgresql/15/main/postgresql.conf << EOF
# 恢复过程中优化
autovacuum = off
checkpoint_timeout = 30min
max_wal_size = 4GB
maintenance_work_mem = 2GB
EOF
# 3. 使用更快的存储设备
# 将恢复目标目录放在SSD上
# 4. 减少WAL日志的数量
# 定期执行基础备份,减少需要应用的WAL日志数量Q4:恢复过程中出现错误怎么办?
A4:
- 查看错误日志:检查PostgreSQL日志文件,了解错误详情
- 分析错误原因:根据错误信息分析问题原因
- 修复问题:
- 如果是WAL文件缺失,确保WAL归档完整
- 如果是权限问题,调整文件权限
- 如果是配置问题,修改配置文件
- 重新恢复:修复问题后重新执行恢复过程
Q5:如何验证恢复后的数据库完整性?
A5:
bash
# 1. 检查数据一致性
psql -h localhost -U postgres -c "SELECT COUNT(*) FROM table1;" # 与预期一致
psql -h localhost -U postgres -c "SELECT * FROM table1 WHERE id = 1;" # 检查特定数据
# 2. 执行数据库一致性检查
psql -h localhost -U postgres -c "VACUUM ANALYZE VERBOSE;" # 检查并优化表
psql -h localhost -U postgres -c "REINDEX DATABASE mydb;" # 重建索引
# 3. 运行应用测试
# 执行应用的单元测试或集成测试,验证数据库功能正常Q6:完全恢复和时间点恢复有什么区别?
A6:
| 特性 | 完全恢复 | 时间点恢复 |
|---|---|---|
| 恢复目标 | 最新状态 | 特定时间点 |
| WAL应用 | 所有可用WAL | 到目标时间点的WAL |
| 恢复命令 | 不需要recovery_target_*参数 | 需要recovery_target_time或recovery_target_xid |
| 适用场景 | 灾难恢复、系统迁移 | 误操作恢复、数据回溯 |
| 恢复后状态 | 包含所有已提交事务 | 只包含到目标时间点的事务 |
