问题概述
架构:集中式1主2备。
参数:synchronous_commit=on,wal_sender_timeout=5s
同步备设定:dn_6001同步备为dn_6002,dn_6002同步备为dn_6001,dn_6003同步备为any(dn_6001,dn_6002)
在主节点执行任意sql语句后持续处于运行状态(即使超过了wal_sender_timeout设定的5s也不退出)。
问题原因
在一个主备集群中,参数synchronous_commit为on说明为同步模式(需要wal日志发送到同步备并持久化到磁盘后事务才能正常commit),这个参数严格要求了主节点和同步备的一致性,如果主节点的同步备状态异常(如脑裂、关机等情况发生)且集群中只有异步备存在时,主节点会一直等待同步备的连接,只要集群中不存在任何同步备,主节点的等待状态就会一直持续且不会受到wal_sender_timeout的影响,在生产环境中使用这种集中式的架构时,面对各种异常的场景(包括上述场景)需要体现出数据库的高可用特性(主备转换、持续服务等),显而易见上述情况是不符合高可用要求的,问题本身的原因是synchronous_commit为on时,必要要求当前主节点的同步备(synchronous_standby_names)状态正常,否则就会出现持续阻塞等待的情况。
场景复现
1. 初始集群状态
2.关闭主节点,查询集群状态
3.到现在的主节点上,gsql进数据库,查看参数与复制流状态
4.写操作测试
5.查看pg_stat_activity,说明sql一直在执行中且不退出
解决方案
-
待原主恢复后重新连接到集群,这个过程所需要的时间是不可控的,主机down的这段时间内新主无法对外持续提供服务,不能体现出高可用,该方法不推荐
-
修改synchronous_commit=off后复现上述操作可以正常创建,但是异步可能会导致数据的丢失,生产环境下synchronous_commit一般为on,该方法不推荐
-
设定当前主节点(dn_6002)的synchronous_standby_names为’*’,意思就是不单单指定dn_6001为同步备,集群中所有的备节点都可作为同步备,包括dn_6003,可选推荐
-
设置参数文件的most_available_sync参数为on开启最大可用同步模式,异常的同步备会自动转变为异步备,该模式不会如第3点解决方案去转化异步备为同步备,而是仍然保持dn_6003的异步关系,该模式下并不会导致因同步备异常导致的阻塞情况,可选推荐
待原主恢复后重新连接到集群,这个过程所需要的时间是不可控的,主机down的这段时间内新主无法对外持续提供服务,不能体现出高可用,该方法不推荐
修改synchronous_commit=off后复现上述操作可以正常创建,但是异步可能会导致数据的丢失,生产环境下synchronous_commit一般为on,该方法不推荐
设定当前主节点(dn_6002)的synchronous_standby_names为’*’,意思就是不单单指定dn_6001为同步备,集群中所有的备节点都可作为同步备,包括dn_6003,可选推荐
设置参数文件的most_available_sync参数为on开启最大可用同步模式,异常的同步备会自动转变为异步备,该模式不会如第3点解决方案去转化异步备为同步备,而是仍然保持dn_6003的异步关系,该模式下并不会导致因同步备异常导致的阻塞情况,可选推荐