无第三方工具下避免PostgreSQL脑裂及阻止旧主节点自启咨询
解决PostgreSQL流复制旧主恢复后的脑裂与数据不一致问题
针对你使用rh-postgresql95搭建流复制、依赖Shell脚本做主从切换的场景,结合测试中遇到的旧主恢复后JDBC优先连接导致数据不一致的问题,给你几个实用的落地方案:
一、彻底阻止旧主节点自动启动(根源预防)
既然你已经用Shell脚本做故障探测和主从切换,完全可以在切换逻辑里加上远程禁用旧主PostgreSQL服务自启的步骤,确保它服务器恢复后不会自动拉起服务:
- 如果是systemd管理服务(RHEL/CentOS 7+),切换时执行:
ssh node1 "sudo systemctl disable rh-postgresql95-postgresql && sudo systemctl stop rh-postgresql95-postgresql" - 要是用init.d脚本(老版本系统),对应命令:
ssh node1 "sudo chkconfig rh-postgresql95-postgresql off && sudo service rh-postgresql95-postgresql stop"
这样就算旧主服务器意外重启,PostgreSQL也不会自动启动,从根源上避免它抢主的风险。
二、让旧主恢复后自动进入只读/从属状态(容错兜底)
如果担心旧主被手动启动,或者之后需要把它作为备用备库,可以在切换时提前修改旧主的配置,确保它启动后无法接受写请求:
- 强制设置只读模式:
切换时远程修改旧主的postgresql.conf:
同时把ssh node1 "echo 'default_transaction_read_only = on' >> /var/opt/rh/rh-postgresql95/lib/pgsql/data/postgresql.conf"hot_standby设为on,让它启动后自动进入备库模式,即使之前是主库也无法接受写操作。 - 通过pg_hba限制写连接:
临时添加规则,拒绝应用服务器的写IP连接(假设应用IP段是192.168.1.0/24):
这样就算旧主被启动,应用也无法通过它写入数据,避免数据不一致。ssh node1 "echo 'host accounting all 192.168.1.0/24 reject' >> /var/opt/rh/rh-postgresql95/lib/pgsql/data/pg_hba.conf"
三、优化JDBC连接串,避免优先连接旧主
你的JDBC串因为node1在首位,导致旧主恢复后客户端优先连它,调整参数让驱动正确识别当前主节点:
- 加上
loadBalanceHosts=true和connectTimeout=5,让驱动在连接时主动检测节点状态,跳过无法提供主服务的节点:
这样当旧主恢复但不是主节点时,驱动会自动尝试连接node2(当前主),不会再优先选择node1。jdbc:postgresql://node1,node2/accounting?targetServerType=master&loadBalanceHosts=true&connectTimeout=5
四、切换后将旧主重新纳入集群(恢复后作为备库)
如果之后需要把旧主重新加入集群,不要直接启动它,而是先让它从新主节点同步最新数据:
- 停止旧主的PostgreSQL服务(如果已经启动)
- 删除旧主数据目录下的所有文件(保留
pg_hba.conf、postgresql.conf等配置文件) - 用
pg_basebackup从新主拉取最新数据:sudo -u postgres pg_basebackup -h node2 -D /var/opt/rh/rh-postgresql95/lib/pgsql/data -P -U replication -X stream - 创建
recovery.conf(rh-postgresql95还未改用postgresql.auto.conf),指定新主为同步源:standby_mode = 'on' primary_conninfo = 'host=node2 port=5432 user=replication password=your_repl_password' trigger_file = '/tmp/promote_me' - 启动旧主服务,它会自动作为新主的备库同步数据,彻底解决数据不一致问题。
内容的提问来源于stack exchange,提问作者YogeshR
相关产品推荐
相关产品推荐

