外观
PostgreSQL 复制失败处理
复制失败的定义
复制失败是指PostgreSQL主从复制系统中,从库无法正常接收、应用或同步主库的WAL日志,导致主从数据不一致或复制关系中断的情况。
复制失败的影响
- 数据不一致:主从库数据出现差异,影响数据可靠性
- 高可用失效:无法进行故障切换,影响系统可用性
- 读写分离不可用:应用无法使用从库进行读操作,增加主库负载
- 恢复能力下降:失去从库备份,增加数据丢失风险
- 业务中断风险:主库故障时无法快速恢复服务
复制失败的常见类型
- 连接失败:主从库之间网络连接中断
- 同步失败:从库无法接收或应用WAL日志
- 延迟超限:复制延迟超过设定阈值
- 复制槽故障:复制槽异常导致WAL日志丢失
- 配置错误:复制配置参数错误
- 版本不兼容:主从库PostgreSQL版本差异过大
复制失败的原因分析
网络问题
网络中断
- 物理网络故障
- 防火墙配置错误
- 网络带宽不足
- 网络延迟过高
连接配置问题
- 监听地址配置错误
- 端口配置错误
- 认证配置错误
- 连接数限制
配置错误
复制参数配置错误
max_wal_senders设置过小wal_keep_size设置不足hot_standby配置错误primary_conninfo配置错误
权限配置错误
- 复制用户权限不足
pg_hba.conf配置错误- 认证方法配置错误
WAL配置错误
wal_level配置过低archive_mode配置错误archive_command配置错误
资源不足
磁盘空间不足
- 主库WAL日志堆积
- 从库数据目录满
- 归档目录空间不足
内存不足
- 从库
shared_buffers不足 - 从库
work_mem不足 - 系统内存不足导致OOM
- 从库
CPU资源不足
- 从库CPU使用率过高
- 主库WAL生成速率超过从库处理能力
- 并行查询消耗过多CPU资源
数据不一致
WAL日志损坏
- 主库WAL日志文件损坏
- 归档WAL日志损坏
- 网络传输中WAL日志损坏
从库数据损坏
- 从库数据文件损坏
- 从库索引损坏
- 从库系统表损坏
初始同步不完整
- 基础备份不完整
- 基础备份与WAL日志不匹配
- 初始同步过程中断
软件问题
版本不兼容
- 主从库PostgreSQL版本差异过大
- 扩展版本不兼容
- 操作系统版本差异
软件bug
- PostgreSQL内核bug
- 复制相关功能bug
- 第三方扩展bug
配置变更
- 主库参数变更未同步到从库
- 从库配置文件修改错误
- 硬件配置变更
复制失败的诊断方法
查看复制状态
主库复制状态查询
sql-- 查看发送者进程状态 SELECT * FROM pg_stat_replication; -- 查看复制槽状态 SELECT * FROM pg_replication_slots; -- 查看WAL发送统计 SELECT * FROM pg_stat_wal; -- 查看连接数 SELECT count(*) FROM pg_stat_activity WHERE backend_type = 'walsender';从库复制状态查询
sql-- 查看WAL接收器状态 SELECT * FROM pg_stat_wal_receiver; -- 查看从库同步状态 SELECT * FROM pg_stat_replication; -- 查看复制延迟 SELECT now() - pg_last_xact_replay_timestamp() AS replication_delay; -- 查看恢复状态 SELECT * FROM pg_stat_wal_receiver;系统级复制状态检查
bash# 检查主库WAL发送进程 ps aux | grep wal sender process # 检查从库WAL接收进程 ps aux | grep wal receiver process # 检查从库恢复进程 ps aux | grep startup process
分析日志文件
主库日志分析
bash# 查看主库日志中的复制相关信息 grep -i "wal sender\|replication" /var/log/postgresql/postgresql-14-main.log # 查看错误信息 grep -i "error\|warning\|fatal" /var/log/postgresql/postgresql-14-main.log从库日志分析
bash# 查看从库日志中的复制相关信息 grep -i "wal receiver\|recovery\|standby" /var/log/postgresql/postgresql-14-main.log # 查看恢复过程日志 grep -i "restore\|apply\|recover" /var/log/postgresql/postgresql-14-main.log系统日志分析
bash# 查看系统日志中的网络相关信息 grep -i "network\|interface\|firewall" /var/log/syslog # 查看磁盘空间相关信息 grep -i "disk\|space\|full" /var/log/syslog
检查系统资源
磁盘空间检查
bash# 检查主库磁盘空间 df -h /var/lib/postgresql/14/main # 检查从库磁盘空间 df -h /var/lib/postgresql/14/standby # 检查WAL归档目录空间 df -h /path/to/wal/archive内存使用检查
bash# 查看内存使用情况 free -h # 查看PostgreSQL进程内存使用 ps aux --sort=-%mem | grep postgresCPU使用检查
bash# 查看CPU使用率 top # 查看PostgreSQL进程CPU使用 ps aux --sort=-%cpu | grep postgres网络连接检查
bash# 测试主从库之间的网络连接 ping -c 5 主库IP # 测试PostgreSQL端口连通性 telnet 主库IP 5432 # 使用psql测试连接 psql -h 主库IP -U replication -d postgres
验证配置
主库配置检查
sql-- 检查复制相关参数 SHOW wal_level; SHOW max_wal_senders; SHOW wal_keep_size; SHOW archive_mode; SHOW archive_command;从库配置检查
sql-- 检查恢复相关参数 SHOW hot_standby; SHOW max_standby_streaming_delay; SHOW wal_receiver_status_interval; -- 检查primary_conninfo配置 SELECT setting FROM pg_settings WHERE name = 'primary_conninfo';配置文件检查
bash# 检查主库pg_hba.conf grep -i replication /etc/postgresql/14/main/pg_hba.conf # 检查从库recovery.conf或postgresql.auto.conf grep -i primary_conninfo /var/lib/postgresql/14/standby/postgresql.auto.conf
复制失败的恢复步骤
简单复制失败的恢复
重启WAL接收器
bash# 从库重启PostgreSQL服务 systemctl restart postgresql重新建立复制连接
sql-- 从库中重新启动恢复进程 SELECT pg_reload_conf();调整复制参数
sql-- 主库增加max_wal_senders ALTER SYSTEM SET max_wal_senders = 10; SELECT pg_reload_conf(); -- 主库增加wal_keep_size ALTER SYSTEM SET wal_keep_size = '1GB'; SELECT pg_reload_conf();
中等复制失败的恢复
重建复制槽
sql-- 主库删除失效的复制槽 SELECT pg_drop_replication_slot('slot_name'); -- 主库重新创建复制槽 SELECT pg_create_physical_replication_slot('slot_name');修复WAL归档问题
bash# 检查归档命令 tail -n 10 /var/log/postgresql/postgresql-14-main.log | grep archive # 修复归档目录权限 chown -R postgres:postgres /path/to/wal/archive chmod 700 /path/to/wal/archive清理旧WAL日志
sql-- 主库手动清理WAL日志(谨慎使用) SELECT pg_switch_wal(); -- 检查WAL日志保留情况 SELECT pg_walfile_name(pg_current_wal_lsn());
复杂复制失败的恢复
从库重建(基于pg_basebackup)
bash# 停止从库服务 systemctl stop postgresql # 清空从库数据目录 rm -rf /var/lib/postgresql/14/standby/* # 使用pg_basebackup重新同步 pg_basebackup -h 主库IP -p 5432 -U replication -D /var/lib/postgresql/14/standby -Fp -Xs -P -R # 启动从库服务 systemctl start postgresql从库重建(基于归档恢复)
bash# 停止从库服务 systemctl stop postgresql # 清空从库数据目录 rm -rf /var/lib/postgresql/14/standby/* # 恢复基础备份 tar -xzf /path/to/base/backup.tar.gz -C /var/lib/postgresql/14/standby # 配置recovery.signal echo "standby_mode = 'on'" > /var/lib/postgresql/14/standby/recovery.signal echo "primary_conninfo = 'host=主库IP port=5432 user=replication password=密码'" >> /var/lib/postgresql/14/standby/recovery.signal echo "restore_command = 'cp /path/to/wal/archive/%f %p'" >> /var/lib/postgresql/14/standby/recovery.signal # 启动从库服务 systemctl start postgresql主库故障切换
bash# 在从库上执行故障切换 pg_ctl promote -D /var/lib/postgresql/14/standby # 或使用SQL命令 SELECT pg_promote();修复数据不一致
sql-- 检查主从数据一致性 SELECT * FROM dblink('host=主库IP user=postgres dbname=dbname', 'SELECT id FROM table_name ORDER BY id') AS t(id int) EXCEPT SELECT id FROM table_name ORDER BY id; -- 修复数据不一致(谨慎使用) -- 注意:此操作可能导致数据丢失,建议在专业人员指导下进行
不同类型复制的故障处理
流复制故障处理
流复制故障特征
- 从库
pg_stat_wal_receiver状态异常 - 主库
pg_stat_replication中对应从库消失 - 复制延迟持续增加
- 从库
流复制故障恢复步骤
- 检查网络连接
- 检查主库
max_wal_senders设置 - 检查
wal_keep_size或复制槽配置 - 重启从库WAL接收器
- 必要时重建从库
逻辑复制故障处理
逻辑复制故障特征
- 发布者或订阅者日志中出现错误
- 订阅状态显示为
down - 复制进度停滞
逻辑复制故障恢复步骤
sql-- 检查逻辑复制状态 SELECT * FROM pg_stat_subscription; SELECT * FROM pg_stat_publication; -- 重启逻辑复制 ALTER SUBSCRIPTION subscription_name REFRESH PUBLICATION; -- 重新创建逻辑复制 DROP SUBSCRIPTION IF EXISTS subscription_name; CREATE SUBSCRIPTION subscription_name CONNECTION 'host=主库IP port=5432 user=replication dbname=dbname' PUBLICATION publication_name;逻辑复制冲突处理
sql-- 查看冲突信息 SELECT * FROM pg_stat_database_conflicts; -- 处理冲突(根据实际情况选择) -- 1. 跳过冲突事务 ALTER SUBSCRIPTION subscription_name SET (skip_errors = true); -- 2. 手动解决冲突后重启复制 -- 3. 重新初始化订阅
物理复制故障处理
物理复制故障特征
- 从库无法启动
- 从库日志中出现数据损坏错误
- 主从库WAL日志不匹配
物理复制故障恢复步骤
- 检查从库数据文件完整性
- 验证基础备份的完整性
- 重建从库
- 确保主从库版本兼容
- 检查硬件故障
复制失败的预防措施
监控复制状态
设置监控告警
- 复制延迟超过阈值告警
- 复制连接中断告警
- 从库状态异常告警
- WAL日志堆积告警
使用监控工具
- Prometheus + Grafana
- Zabbix
- Nagios
- pgMonitor
自定义监控脚本
bash# 检查复制延迟的脚本示例 REPLICATION_DELAY=$(psql -h 从库IP -U postgres -t -c "SELECT EXTRACT(EPOCH FROM (now() - pg_last_xact_replay_timestamp()))::int") if [ $REPLICATION_DELAY -gt 300 ]; then echo "复制延迟超过5分钟,当前延迟:${REPLICATION_DELAY}秒" # 发送告警 fi
定期测试复制
定期进行故障切换测试
- 每季度至少进行一次手动故障切换
- 记录切换时间和过程
- 测试回切流程
定期验证数据一致性
- 使用
pg_verifybackup验证备份完整性 - 定期比较主从库关键表数据
- 使用第三方工具如
pgAdmin进行数据一致性检查
- 使用
测试恢复流程
- 定期从备份恢复从库
- 测试不同场景下的恢复时间
- 验证恢复后的数据完整性
合理配置复制参数
主库复制参数优化
sql-- 合理设置WAL保留 ALTER SYSTEM SET wal_keep_size = '2GB'; -- 增加WAL发送进程数 ALTER SYSTEM SET max_wal_senders = 10; -- 启用复制槽 -- 注意:使用复制槽时需确保从库正常运行,避免WAL日志堆积从库复制参数优化
sql-- 设置合理的流复制延迟 ALTER SYSTEM SET max_standby_streaming_delay = '30s'; -- 设置WAL接收器状态报告间隔 ALTER SYSTEM SET wal_receiver_status_interval = '10s'; -- 启用热备 ALTER SYSTEM SET hot_standby = on;网络参数优化
- 调整TCP连接超时参数
- 优化网络缓冲区大小
- 使用专用网络进行复制
保持软件版本一致
主从库版本匹配
- 确保主从库PostgreSQL版本一致
- 版本差异不超过一个主版本
- 及时更新补丁版本
扩展版本兼容
- 确保主从库扩展版本一致
- 升级扩展时同步更新主从库
- 测试扩展兼容性
操作系统版本兼容
- 主从库操作系统版本尽量一致
- 确保系统库版本兼容
- 测试跨平台复制兼容性
实施高可用架构
使用Patroni或repmgr
- 自动故障检测和切换
- 自动恢复复制关系
- 集中管理复制配置
实施多从库架构
- 部署多个从库,分散风险
- 不同从库使用不同的复制方式
- 跨可用区部署从库
使用负载均衡
- 配置PgBouncer或Pgpool-II
- 自动检测从库状态
- 自动剔除故障从库
复制失败的监控与告警
关键监控指标
复制状态指标
- 复制延迟时间
- 复制连接状态
- WAL发送速率
- WAL应用速率
- 复制槽状态
系统资源指标
- 磁盘使用率
- 内存使用率
- CPU使用率
- 网络带宽使用率
- 网络延迟
PostgreSQL指标
- 连接数
- WAL日志生成速率
- 锁等待情况
- 慢查询数量
- 缓冲区命中率
告警配置建议
| 告警项 | 告警阈值 | 告警级别 | 处理建议 |
|---|---|---|---|
| 复制延迟 | > 300秒 | 警告 | 检查网络和系统资源 |
| 复制延迟 | > 600秒 | 严重 | 立即检查复制状态,必要时重建从库 |
| 复制连接中断 | 连接数=0 | 严重 | 检查网络连接和主库状态 |
| 从库磁盘使用率 | > 90% | 警告 | 清理磁盘空间或扩容 |
| 从库磁盘使用率 | > 95% | 严重 | 立即清理磁盘空间 |
| 主库WAL堆积 | > 100GB | 警告 | 检查从库状态和复制槽配置 |
| 复制槽溢出 | wal_keep_size不足 | 严重 | 增加wal_keep_size或修复从库 |
常见问题与解决方案
Q1: 从库无法连接到主库怎么办?
A1: 从库无法连接到主库的解决步骤:
检查网络连接
bashping 主库IP telnet 主库IP 5432检查主库监听配置
sqlSHOW listen_addresses; SHOW port;检查pg_hba.conf配置
bashgrep -i replication /etc/postgresql/14/main/pg_hba.conf检查复制用户权限
sqlSELECT usename, usesuper, replication FROM pg_user WHERE usename = 'replication';检查主库max_wal_senders设置
sqlSHOW max_wal_senders; SELECT count(*) FROM pg_stat_replication;
Q2: 复制延迟持续增加怎么办?
A2: 复制延迟持续增加的解决步骤:
检查从库系统资源
bashtop df -h free -h检查主库WAL生成速率
sqlSELECT * FROM pg_stat_wal;检查从库WAL应用速率
sqlSELECT * FROM pg_stat_bgwriter;调整复制参数
sql-- 主库增加wal_keep_size ALTER SYSTEM SET wal_keep_size = '2GB'; -- 从库调整max_standby_streaming_delay ALTER SYSTEM SET max_standby_streaming_delay = '60s';考虑升级硬件
- 增加从库CPU核心数
- 提高从库内存
- 使用更快的存储设备
- 优化网络带宽
Q3: 复制槽导致主库WAL日志堆积怎么办?
A3: 复制槽导致WAL日志堆积的解决步骤:
检查复制槽状态
sqlSELECT * FROM pg_replication_slots;检查WAL日志使用情况
bashdu -sh /var/lib/postgresql/14/main/pg_wal/*修复或删除失效的复制槽
sql-- 修复从库连接 -- 或删除失效的复制槽 SELECT pg_drop_replication_slot('slot_name');调整复制槽配置
sql-- 使用临时复制槽 CREATE_REPLICATION_SLOT slot_name TEMPORARY;
Q4: 从库重建后仍然无法同步怎么办?
A4: 从库重建后无法同步的解决步骤:
检查基础备份完整性
bash# 验证基础备份 pg_verifybackup /path/to/base/backup检查WAL日志完整性
bash# 验证WAL日志 pg_waldump /path/to/wal/archive/000000010000000000000001检查主从库版本兼容性
bash# 检查主库版本 psql -h 主库IP -U postgres -c "SELECT version();" # 检查从库版本 psql -h 从库IP -U postgres -c "SELECT version();"检查恢复配置
bashcat /var/lib/postgresql/14/standby/postgresql.auto.conf查看详细日志
bashtail -n 100 /var/log/postgresql/postgresql-14-main.log
常见问题(FAQ)
Q1: 复制失败会导致数据丢失吗?
A1: 复制失败是否导致数据丢失取决于复制配置:
- 异步复制:可能导致数据丢失,因为主库提交事务后立即返回,不等待从库确认
- 同步复制:主库提交事务后等待从库确认,不会导致数据丢失,但会影响性能
- 半同步复制:主库提交事务后等待至少一个从库确认,平衡了性能和数据安全性
建议根据业务需求选择合适的复制模式,并配置适当的复制槽或WAL保留策略。
Q2: 如何区分是主库问题还是从库问题?
A2: 区分主库和从库问题的方法:
- 检查多个从库:如果所有从库都出现问题,可能是主库问题
- 检查主库日志:主库日志中是否有错误信息
- 检查从库日志:从库日志中是否有连接或应用错误
- 测试主库连接:使用psql测试能否连接到主库
- 检查主库资源:主库是否有资源瓶颈
Q3: 复制失败后如何验证数据一致性?
A3: 验证数据一致性的方法:
使用pg_syncdiff工具
- 专门用于比较PostgreSQL主从库数据一致性
- 支持表级和行级比较
- 生成差异报告
使用check_postgres插件
- 提供复制一致性检查功能
- 可以集成到监控系统
- 支持自动告警
手动验证关键表
sql-- 比较表行数 SELECT COUNT(*) FROM table_name; -- 比较表哈希值 SELECT md5(CAST((array_agg(t.* ORDER BY id)) AS text)) FROM table_name t;
Q4: 如何预防复制失败?
A4: 预防复制失败的措施:
- 实施完善的监控和告警
- 定期进行复制测试和演练
- 保持主从库版本一致
- 合理配置复制参数
- 使用高可用工具如Patroni
- 部署多个从库,分散风险
- 定期备份和验证
- 培训团队成员,提高故障处理能力
Q5: 复制失败后需要多长时间恢复?
A5: 复制失败的恢复时间取决于:
- 故障类型:简单故障几分钟内恢复,复杂故障可能需要数小时
- 数据量大小:数据量越大,重建从库时间越长
- 网络带宽:网络带宽影响基础备份传输时间
- 系统资源:CPU、内存和磁盘速度影响WAL应用速度
- 恢复经验:团队故障处理经验影响恢复效率
建议制定详细的恢复计划,并定期进行演练,以缩短实际恢复时间。
Q6: 如何在不影响业务的情况下重建从库?
A6: 在线重建从库的方法:
使用pg_basebackup的--checkpoint选项
bashpg_basebackup -h 主库IP -p 5432 -U replication -D /var/lib/postgresql/14/standby -Fp -Xs -P -R --checkpoint=fast使用并行备份
bash# 使用pg_basebackup的-j选项启用并行备份 pg_basebackup -h 主库IP -p 5432 -U replication -D /var/lib/postgresql/14/standby -Fp -Xs -P -R -j 4使用现有从库进行级联复制
- 从现有从库创建新从库,减少主库负载
- 使用级联复制配置
- 适用于多从库架构
选择业务低峰期进行重建
- 避免在业务高峰期重建从库
- 提前通知相关团队
- 准备回滚方案
