外观
PostgreSQL 手动切换流程
手动切换概述
什么是手动切换
手动切换(Manual Switchover)是指在数据库管理员的控制下,将主库的角色切换到备库,同时将原主库转换为备库的操作。这种操作通常在以下场景中使用:
- 主库计划维护
- 主库硬件升级
- 数据中心迁移
- 负载均衡调整
- 灾备演练
手动切换与故障转移的区别
| 特性 | 手动切换 | 故障转移 |
|---|---|---|
| 触发方式 | 手动执行 | 自动触发 |
| 主库状态 | 正常运行 | 已故障 |
| 数据完整性 | 确保数据一致 | 可能丢失部分数据 |
| 切换时间 | 可控 | 不可控 |
| 风险 | 低 | 较高 |
准备工作
在执行手动切换前,需要完成以下准备工作:
检查主备状态
- 确保主备库复制状态正常
- 检查复制延迟,确保延迟在可接受范围内
- 验证备库已应用所有WAL日志
备份重要数据
- 执行主库全量备份
- 备份关键配置文件
- 确保备份可恢复
通知相关团队
- 通知应用团队准备切换
- 通知监控团队关注切换过程
- 建立切换沟通渠道
准备切换工具
- 确保psql工具可用
- 准备切换脚本
- 准备验证脚本
手动切换执行步骤
1. 检查复制状态
在主库上执行以下命令,检查复制状态:
sql
-- 查看主库复制状态
SELECT
application_name AS 备库名称,
client_addr AS 备库IP,
state AS 复制状态,
sync_state AS 同步状态,
pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) AS 回放延迟_bytes,
now() - replay_lag AS 时间延迟
FROM pg_stat_replication;
-- 检查主库WAL位置
SELECT pg_current_wal_lsn() AS 主库当前LSN;在备库上执行以下命令,检查备库状态:
sql
-- 检查备库是否处于恢复状态
SELECT pg_is_in_recovery();
-- 查看备库恢复进度
SELECT
last_wal_receive_lsn AS 最后接收LSN,
last_wal_replay_lsn AS 最后回放LSN,
last_wal_replay_time AS 最后回放时间
FROM pg_stat_wal_receiver;
-- 检查备库是否已应用所有WAL
SELECT pg_last_wal_replay_lsn() AS 备库当前LSN;2. 停止主库写入操作
在执行切换前,需要停止主库的写入操作,确保所有WAL日志都已传输到备库:
方法1:使用pg_ctl stop --mode=fast
bash
# 在主库上执行
pg_ctl stop -D /var/lib/pgsql/14/data --mode=fast方法2:使用SQL命令
sql
-- 在主库上执行
SELECT pg_wal_replay_resume();
SELECT pg_ctl('main', 'stop', 'fast');3. 验证备库已应用所有WAL
在备库上执行以下命令,验证备库已应用所有WAL日志:
sql
-- 检查备库恢复状态
SELECT pg_is_in_recovery();
-- 查看备库最后回放LSN
SELECT pg_last_wal_replay_lsn() AS 备库当前LSN;
-- 确保备库已接收并应用所有WAL
-- 对比主库和备库的LSN,确保两者一致4. 提升备库为主库
在备库上执行以下命令,将备库提升为主库:
PostgreSQL 12+版本
bash
# 在备库上执行
pg_ctl promote -D /var/lib/pgsql/14/dataPostgreSQL 9.6-11版本
bash
# 在备库上执行
pg_ctl promote -D /var/lib/pgsql/9.6/data使用SQL命令(所有版本)
sql
-- 在备库上执行
SELECT pg_promote(wait_seconds => 60, write_promote_file => true);5. 验证新主库状态
在提升后的主库上执行以下命令,验证主库状态:
sql
-- 检查是否为主库(返回false)
SELECT pg_is_in_recovery();
-- 查看主库状态
SELECT
pg_current_wal_lsn() AS 当前LSN,
pg_is_in_recovery() AS 是否为主库,
current_database() AS 当前数据库;
-- 检查监听状态
SELECT * FROM pg_stat_activity WHERE backend_type = 'walsender';6. 将原主库转换为备库
1. 清理原主库数据目录
bash
# 停止原主库服务
pg_ctl stop -D /var/lib/pgsql/14/data --mode=fast
# 清理数据目录(保留配置文件)
rm -rf /var/lib/pgsql/14/data/*2. 从新主库创建基础备份
bash
# 使用pg_basebackup创建基础备份
pg_basebackup -h 新主库IP -p 5432 -U replication -D /var/lib/pgsql/14/data -Fp -Xs -P -R3. 配置原主库为备库
编辑/var/lib/pgsql/14/data/postgresql.auto.conf文件,确保包含以下配置:
primary_conninfo = 'host=新主库IP port=5432 user=replication password=replication_pass application_name=原主库名称'4. 启动原主库
bash
# 启动原主库服务
pg_ctl start -D /var/lib/pgsql/14/data7. 验证新的主备关系
在新主库上执行以下命令,验证原主库已转换为备库:
sql
-- 查看新的复制状态
SELECT
application_name AS 备库名称,
client_addr AS 备库IP,
state AS 复制状态,
sync_state AS 同步状态,
pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) AS 回放延迟_bytes
FROM pg_stat_replication;在原主库(现在是备库)上执行以下命令,验证备库状态:
sql
-- 检查是否为备库(返回true)
SELECT pg_is_in_recovery();
-- 查看备库恢复进度
SELECT
last_wal_receive_lsn AS 最后接收LSN,
last_wal_replay_lsn AS 最后回放LSN,
last_wal_replay_time AS 最后回放时间
FROM pg_stat_wal_receiver;应用切换
1. 更新应用连接配置
- 更新应用数据库连接字符串,指向新主库
- 更新连接池配置
- 更新监控配置
2. 测试应用连接
bash
# 使用psql测试连接
psql -h 新主库IP -p 5432 -U appuser -d mydb
# 执行简单查询测试
SELECT 1;
INSERT INTO test_table (name) VALUES ('switchover_test');
SELECT * FROM test_table WHERE name = 'switchover_test';3. 逐步恢复流量
- 先恢复部分应用流量
- 监控系统性能和稳定性
- 确认无问题后,恢复全部流量
切换验证
1. 数据一致性验证
sql
-- 在新主库上执行
SELECT count(*) FROM important_table;
-- 在原主库(备库)上执行
SELECT count(*) FROM important_table;
-- 确保两个库的计数一致2. 复制状态验证
sql
-- 在新主库上执行
SELECT
application_name,
client_addr,
state,
sync_state,
pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) AS 延迟_bytes
FROM pg_stat_replication;
-- 确保所有备库状态正常,延迟在可接受范围内3. 应用功能验证
- 验证核心业务功能
- 验证读写操作正常
- 验证事务完整性
- 验证报表查询正常
4. 监控指标验证
- 检查CPU使用率
- 检查内存使用率
- 检查磁盘I/O
- 检查网络连接数
- 检查复制延迟
回滚方案
如果切换过程中出现问题,需要执行回滚操作。以下是回滚步骤:
1. 停止新主库写入
sql
-- 在新主库上执行,禁止写入
REVOKE ALL ON DATABASE mydb FROM public;2. 恢复原主库
bash
# 停止原主库(现在是备库)
pg_ctl stop -D /var/lib/pgsql/14/data --mode=fast
# 恢复原主库备份
pg_restore -h localhost -p 5432 -U postgres -d mydb /path/to/full_backup.sql
# 启动原主库
pg_ctl start -D /var/lib/pgsql/14/data3. 重新配置备库
bash
# 停止新主库
pg_ctl stop -D /var/lib/pgsql/14/data --mode=fast
# 清理数据目录
rm -rf /var/lib/pgsql/14/data/*
# 从原主库创建基础备份
pg_basebackup -h 原主库IP -p 5432 -U replication -D /var/lib/pgsql/14/data -Fp -Xs -P -R
# 启动备库
pg_ctl start -D /var/lib/pgsql/14/data4. 恢复应用连接
- 更新应用连接配置,指向原主库
- 恢复应用流量
- 验证系统正常运行
最佳实践
1. 制定详细的切换计划
- 编写详细的切换脚本
- 定义清晰的切换步骤和责任人
- 制定明确的回滚方案
- 安排切换时间窗口
2. 进行切换演练
- 在测试环境中进行切换演练
- 记录切换时间和问题
- 优化切换流程
- 培训相关人员
3. 监控切换过程
- 使用监控工具跟踪切换过程
- 记录关键指标变化
- 建立实时沟通渠道
- 及时处理异常情况
4. 控制切换时间
- 尽量在业务低峰期执行切换
- 限制切换时间窗口
- 优化切换步骤,减少切换时间
- 准备应急方案
5. 文档记录
- 记录切换过程的详细信息
- 记录切换中遇到的问题和解决方案
- 记录切换前后的系统状态
- 更新相关文档
常见问题与解决方案
1. 切换后复制延迟持续增长
问题现象:
- 新主库和备库之间的复制延迟持续增长
- 备库无法跟上主库的写入速度
解决方案:
- 检查备库的系统资源使用情况
- 调整备库的PostgreSQL参数
- 考虑使用更强大的硬件
- 优化主库的写入模式
2. 备库提升失败
问题现象:
- 执行pg_promote()失败
- 备库无法转换为主库
解决方案:
- 检查备库的恢复状态
- 验证备库已应用所有WAL日志
- 检查备库的权限设置
- 查看备库日志,分析具体错误
3. 应用连接失败
问题现象:
- 应用无法连接到新主库
- 出现连接超时或认证失败
解决方案:
- 检查新主库的监听配置
- 验证pg_hba.conf配置
- 检查防火墙设置
- 验证应用连接字符串
4. 数据不一致
问题现象:
- 新主库和备库数据不一致
- 应用查询到错误数据
解决方案:
- 执行全量数据校验
- 从备份恢复不一致的数据
- 重新初始化备库
- 检查复制配置
版本差异注意事项
PostgreSQL 9.6
- 不支持pg_promote()函数的wait_seconds参数
- 需要使用recovery.conf配置文件
- 不支持write_promote_file参数
PostgreSQL 10-11
- 支持pg_promote()函数
- 开始支持recovery.signal文件
- 不支持wait_seconds参数
PostgreSQL 12+
- 支持完整的pg_promote()函数参数
- 完全使用recovery.signal替代recovery.conf
- 支持并行复制
- 支持更详细的复制状态监控
总结
手动切换是PostgreSQL高可用架构中的重要操作,需要谨慎计划和执行。通过遵循本文档中的步骤和最佳实践,可以确保切换过程的安全可靠,减少对业务的影响。
在实际生产环境中,建议:
- 定期进行切换演练,熟悉切换流程
- 建立完善的监控和告警机制
- 制定详细的切换计划和回滚方案
- 与相关团队保持良好沟通
- 记录切换过程,持续优化切换流程
通过合理的规划和执行,可以确保PostgreSQL手动切换的成功,提高系统的可用性和可靠性。
