复制槽概念
复制槽(replication slot)在postgresql9.4版本中被引入,引入之初是为了防止备库需要的xlog日志在主库被删除,主库会会根据备库返回的信息确认哪些xlog已不再需要,,才能进行清理。同时主库不会移除那些导致恢复冲突的行,关于恢复冲突,前面有一篇文章讲到过可以通过设置hot_standby_feedback、max_standby_streaming_delay等参数进行预防,但是这些参数只有在主备关系正常时才能起到作用,而replication slot能够确保在主备断连后主库的xlog仍不被清理。
复制槽分为物理复制槽physical replication slot和逻辑复制槽logic replication slot。物理复制槽一般结合流复制一起使用,能够很好的保证备库需要的日志不会在主库删除,本文重点讨论逻辑复制槽。
Logic replication slots一般被用于逻辑异步复制,一个很好的应用就是用于异构数据库之间的逻辑复制。大致原理是将源端xlog进行解码,解析成具体sql,然后到目标端进行回放。支持逻辑解码需要将wal_level设置为logic,logic会在replica的基础上增加一些信息以支持逻辑解码,该模式会增大wal日志的数量,尤其是大量的update,delete操作的库。
逻辑复制槽的出现算是一个创新,相当于官方将xlog解码功能提供到源码中,这是做逻辑同步工具公司的福音,公司只需要使用pg_recvlogic等逻辑解码工具或pg_logic_slot_get_changes()等SQL接口函数将xlog解析成sql文本在目标端回放即可。
需要关注的问题
对于逻辑复制槽,有下面几点需要注意:
①一个逻辑复制槽只能解码一个database,但是一个database可以有多个复制槽进行解码,同一个复制槽可能同时有多个接收端进行订阅。
②复制槽的消息只发送一次,同时它不关心接收端的状态,如果接收端执行失败,那么复制槽不会向前推进,接收端成功后继续从上次失败的位点继续进行消费。
③不支持DDL、列存、压缩表的解码,DDL一般需要需要创建额外的触发器来进行处理,但可以做到表级订阅。
④逻辑复制不能保证数据不丢失,不能用作数据容灾,但是可以用于数据迁移,在主库有大事务的情况下延迟较大。
⑤不使用的复制槽一定要及时删除。
慎用replication slot
上面的第五点是需要特别注意的,也是我说慎用replication slot的原因。
笔者在生产环境多次遇到因为逻辑复制槽造成xlog堆积的问题。我们知道当主备断连的时候逻辑槽会保证主库不清理xlog,这样就会造成xlog堆积。其实不仅是主备断连,当主库没有更新业务的时候,主库的xlog也不会清理,有些人可能会说了,主库都没有业务了,根本就不会生成xlog,那么也不会有xlog堆积的问题了,看似解释很完美,但是我们试想下面这个场景。
如果是多租户的环境呢?如果我在使用一个集群,比如pgxc,集群上有多个数据库,我们为了保证rpo接近0,使用了逻辑复制的方案,其中有两个库都需要同步,需要建立两个逻辑槽。如果其中一个业务很繁忙,每天有大量的跑批操作,但是另一个库不是那么繁忙,或者说在节假日的时候没有业务,这时就需要特别小心了。因为两个库其实共用的是一份xlog日志,其中一个库很麻烦产生大量的xlog,但是另一个库没有业务,会造成该库的逻辑槽的restart_lsn始终不往前推进,这样就造成主库的xlog没法删除,最终造成主库的磁盘爆掉。笔者生产环境中曾经遇到过xlog堆积好几万个的情况,好在当时磁盘容量够大,没有发生事故。
最佳实践
所以在生产环境中如果使用replication slot,有下面几点建议:
①可以增加xlog日志个数的监控,当xlog数量超过正常值时通知dba查找原因。
②做好对每个复制槽同步状态的监控,出现某个槽同步状态异常要及时处理,同步异常会造成lsn不向前推进。
③对于业务很空闲但是数据需要同步的库,可以自定义脚本,定期更新无用表,手工推进lsn。
④如果xlog已经堆积很多磁盘马上要爆炸的情况下,在考虑应急删掉复制槽之前要评估剩余空间是否还有足够富余,因为即使删掉复制槽,xlog也不是马上就会清理,删掉后主库vacuum也会产生较多xlog日志,一定要做好评估。
⑤增加pg_replication_slot()视图中restart_lsn的监控,对于落后较大和长期不推进的lsn进行告警。
好吧,加油吧。
欢迎关注我的公众号:数据库架构之美