作者简介
RICHARD YEN: EnterpriseDB公司的高级支持工程师,支撑EnterpriseDB的整个产品。在加入EnterpriseDB之前,Richard曾担任数据库工程师和WEB开发人员,主要在实际中操作,关注可扩展性、性能和可恢复性等方面。
译者简介
陈雁飞,开源PostgreSQL爱好者,一直从事PostgreSQL数据库运维工作
李冉,瀚高基础软件工具开发工程师。
引言
当我第一次参与Postgres数据库管理的时候,很快就了解了复制的必要性。我的第一个项目是将数据库放在Slony上,这是一种热门的新复制技术,代替笨拙的DRBD配置,并且支持对数据库近实时的副本备份。当然,随着时间和规模的增加,Slony很难满足快速增加的写入流量,并且最终会受到写放大的影响(由于所有操作包含对底层操作,因此每次操作最终会变成对数据库的两次或者更多次写)。当在Postgres9.0版本出现流复制的时候,每个人都觉得自己得到了金牌。流复制不仅速度快,而且它利用了Postgres中已经存在的特性:WAL stream。
距离Postgres9.0版本已经过去很多年了(我们马上见到12版本)。这期间Postgres增加了很多特性,比如热备份、逻辑复制和一些双向Matser-Master复制扩展插件。这个是一条不寻常的成长之路,特别是我记得在大约是在2010年的PGcon大会上一次非正式研讨的时候(BOF),有人说Postgres的路线图中将不会包括复制。
在多年来流复制的所有改进中,我认为一个最容易被误解特性是hot_standby_feedback,因此我希望在这里能够澄清一下。
通过流复制,用户可以建立任意个与主机有克隆复制关系的备服务器,并且这些备服务器也支持一些特定类型的操作。比如OLTP应用程序中只读流量、庞大的定时任务、以及长时间运行的报表查询等,所有这些操作不会影响主服务器上的写入流量。但是,有些人偶尔会遇到查询由于某种原因被终止了,并且在日志中,可以看到类似如下内容:
ERROR: canceling statement due to conflict with recovery
这个错误是一个不幸的现实,没有人会喜欢这个。没有人希望自己的查询被取消,就像没人喜欢在点一个熏牛肉三明治的时候,过了10分钟才被店家告知熏牛肉卖完了。但是,这种情况确实发生了。通常在流复制中一些数据需要重放的时候发生查询冲突的情况,常见的是一些旧数据的删除,无论是删除,还是删除表,甚至VACUUM清理死行数据操作。在Google上搜索Postgres流复制的时候,一些用户建议通过设置hot_standby_feedback参数为on的方式解决遇到的查询冲突问题。很多人很高兴地设置hot_standby_feedback = on,然后业务可以正常运转了,但是我遇到一些客户设置之后仍然会从日志中看到ERROR: canceling statement due to conflict with recovery错误信息。
为什么继续产生查询冲突?
关于Postgres的流复制,需要牢记的重要一点:它的目标是创建数据库副本,并将WAL日志传输到另外一边去。现在,DBA可能有其他的不同目标,包括在备服务器上进行查询和报表操作,但是这个并不是Postgres的目标。DBA可以配置一些GUC参数,用于告诉Postgres在某些方面不需要太激进,以便能预留一点空间在备机上运行查询操作。但是,如果备机没有处理接收到的WAL流文件,那么在pg_xlog/pg_wal目录下的WAL日志将堆积并膨胀,并且使运行的主服务器面临磁盘空间耗尽的风险。
hot_standbt_feedback究竟是做什么的?
这里不想再谈技术细节了,我认为Alexey Lesovsky用一个很好的例子解释了它,并且有源代码提供给有兴趣的人详细阅读。简而言之,改参数表示备机将相关信息发送给主机(pg_stat_replication.backend_xmin值),从而帮助主机确定哪些dead tuple可以安全地被vacuum清理掉。换句话说,当备机上执行查询的时候,会通过设置backend_xmin影响主机的元组可见性判断,从而主机不会vacuum清理相关元组。
-bash-4.1$ psql -p5432 -c "SELECT application_name, backend_start, backend_xmin, state, sent_location, write_location, flush_location, replay_location FROM pg_stat_replication"
application_name | backend_start | backend_xmin | state | sent_location | write_location | flush_location | replay_location
------------------+---------------------------------+-----------------------+-----------+---------------+----------------+----------------+-----------------
walreceiver | 01-MAR-19 23:18:55.31685 +00:00 |{look ma, nothing here}| streaming | 0/6000060 | 0/6000060 | 0/6000060 | 0/6000060
(1 row)
-bash-4.1$ psql -p5433 -c "ALTER SYSTEM SET hot_standby_feedback TO on"
ALTER SYSTEM
-bash-4.1$ pg_ctl -D /var/lib/pgsql/9.6/standby_pgdata restart
waiting for server to shut down.... done
server stopped
server starting
-bash-4.1$ psql -p5432 -c "SELECT application_name, backend_start, backend_xmin, state, sent_location, write_location, flush_location, replay_location FROM pg_stat_replication"
application_name | backend_start | backend_xmin | state | sent_location | write_location | flush_location | replay_location
------------------+----------------------------------+-----------------------+-----------+---------------+----------------+----------------+-----------------
walreceiver | 01-MAR-19 23:21:18.373624 +00:00 | {hs_feedback on} 2346 | streaming | 0/6000060 | 0/6000060 | 0/6000060 | 0/6000060
(1 row)
基本上,这是一个延迟策略,将清除信息排除在WAL之外,因为一旦deaded元组被vacuum清理,清理信息将写入WAL日志流中并在备机上产生冲突。注意这里有一点需要权衡考虑:设置hot_standby_feedback=on可能会导致主机上表发生膨胀,通常这个并不是很重要。但是,即使这样,仍然有一些查询冲突是hot_standby_feedback无法阻止的:
1、对主机对象上请求排他锁
2、断断续续地walreceiver连接进程
3、对少数表的频繁修改
排它锁导致的冲突
如果流复制需要成为一项可靠的技术,那么所有的备机需要和它们的主数据库保持一致。这也就是说主机上所有的修改需要尽可能快发送到备机并恢复,这里需要特别注意的是DDL操作以及其他需要获取排它锁的变化。任何时延都可能导致数据库的不一致(谁会愿意看到已经删除的表?),且当在主机发生故障并且需要立即进行故障转移的时候,最理想的情况是备机与主机之间是完全同步的。因此,DBA希望能尽可能快的重放WAL日志。
一致性还意味着,当Alice和Bob在只读的备机上查询得到的结果是准确的,和主机上运行查询结果一样(当然,除非DBA已经将备机设置在固定时间内跟踪主机,比如在recovery.conf中设置recovery_min_apply_delay参数)。但是,如果有人在数据库里执行一个长时间运行的查询,那么这个查询会阻止WAL日志的重放,因此必须给出一些参数用于取消这些查询操作。DBA可以设置max_standby_archive_delay或max_standby_streaming_delay参数,以便在取消查询前给冲突查询一段时间。这两个参数在设置的要谨慎,需要考虑到业务允许存在的复制时延。
断断续续的walreceiver连接的影响
网络中断将断开walreceiver连接,并最终使得发送给主机的backend_xmin信息失效。也就是说,如果walreceiver连接断开,那么在walreceiver重新连接并告诉主机新的backend_xmin信息之前,主机可以自由地对期望的对象进行vacuum清理。从备机用户角度看,一些非期望的vacuum清理操作可能发生在walreceiver进程重连期间,从而可能导致程出现查询冲突取消的情况。这种情况可以通过流复制槽来缓解,它可以记录断开walreceiver连接的xmin信息。
少量表的频繁写入
VACUUM操作通常不是阻塞的,但是如果存在有足够的查询/删除操作,一个vacuum任务可能会发现一个标记为需要删除的完整页面,在这种情况它将尝试获取对象的排它锁信息,从而将该页面从磁盘上删除,从而减小表占用的空间。从流复制恢复角度看,这种锁行为基本上与DDL操作一样,并且最终可能会导致正在运行中查询被取消掉。
总结
即使设置了hot_standby_feedback=on,仍然有很多种情况会导致查询因为冲突而取消,但是这些情况比较少见。查询pg_stat_database_conflicts信息有助于了解产生取消查询的原因,对找到缓解该问题的方法有很大帮助。最后,hot_standby_feedback只是众多处理备机查询冲突方法中的一种,用户需要明白的一点是:为了保证一致和可靠,这种查询冲突时必须的。无论是通过hot_feed_back参数还是其他方式,设置备机查询为更高优先级,都是以牺牲主备之间复制时延(有时可能会很小)为代价。
原文地址:https://www.enterprisedb.com/blog/why-hotstandbyfeedback-can-be-misleading
译后感
本文介绍的是数据库中备机只读功能,重点说明了三种情况可能会导致备机上查询失败,并介绍了hot_standby_feedback参数并不能完全解决备机查询冲突问题,最后阐述在流复制下,我们的首要目标是确保数据的一致,而不应该将备机的查询设置为更高优先级别。
在日常运维中,随着数据规模的扩大,我们会自然而然的想到使用多个备机进行扩展查询(特别是现在JDBC和libpq接口已经支持多个连接host设置,更加方便实现一主多备集群操作),但是我们不得不接受备机可能存在的延迟、冲突等情况,这一点需要在使用中特别注意。同时,如果我们要在备机上做逻辑备份,也有可能会存在失败的情况。即使我们设置了hot_standby_feedback=on,主机上仍然可能存在请求排他锁的情况,比如autovacuum清理中对页面的truncate操作(WIP: long transactions on hot standby feedback replica / proof of concept)、每个操作中可能触发的HOT pruning对页面的truncate操作(正文中介绍的第三种情况)。因此,如果大家有使用备机查询功能,一定要结合业务需要和数据可靠性要求,合理设置参数。
…
https://zulin.tiancebbs.cn/sh/174.html https://zulin.tiancebbs.cn/sh/1052.html https://su.tiancebbs.cn/hjzl/463502.html https://taicang.tiancebbs.cn/hjzl/465200.html https://wuwei.tiancebbs.cn/qths/467830.html https://www.tiancebbs.cn/qtfwxx/473312.html https://aihuishou.tiancebbs.cn/sh/3506.html https://www.tiancebbs.cn/ershoufang/474503.html https://taicang.tiancebbs.cn/hjzl/456846.html https://guangyuan.tiancebbs.cn/qths/457194.html https://zulin.tiancebbs.cn/sh/2147.html https://aihuishou.tiancebbs.cn/sh/638.html https://sz.tiancebbs.cn/pgjgsc/339616.html https://zulin.tiancebbs.cn/sh/3233.html https://taicang.tiancebbs.cn/hjzl/456889.html https://www.tiancebbs.cn/ershoufang/466951.html https://su.tiancebbs.cn/hjzl/464809.html
顶岗实习个人总结:https://www.henkao.com/xuexi/1791.html 什么是大叔控:https://www.henkao.com/qinggan/13.html 柿子不能和什么食物一起吃:https://www.henkao.com/yinshi/948.html 卫生间防水:https://www.henkao.com/jiaju/74.html 一个字的网名:https://www.henkao.com/wangluo/923.html 六一快乐说说朋友圈:https://www.henkao.com/wangluo/417.html 汇报材料开头:https://www.henkao.com/zhichang/2213.html 思想政治工作总结:https://www.henkao.com/zongjie/1776.html 五味杂陈的心情短语:https://www.henkao.com/qinggan/1695.html 非主流语录:https://www.henkao.com/qinggan/885.html 个性签名男生成熟稳重:https://www.henkao.com/wangluo/829.html 车辆安全管理制度:https://www.henkao.com/zhichang/1984.html 聚酯纤维是啥面料:https://www.henkao.com/jiaju/566.html 八字成语:https://www.henkao.com/xuexi/380.html 简短的劝节哀的句子:https://www.henkao.com/qinggan/643.html 四个字的游戏名:https://www.henkao.com/wangluo/1204.html 王者情侣名:https://www.henkao.com/wangluo/1567.html 教师教学工作计划:https://www.henkao.com/zhichang/2137.html 高端逗比的游戏名字:https://www.henkao.com/wangluo/1088.html 学习党章思想汇报:https://www.henkao.com/xuexi/2209.html 有点撒娇还甜的网名:https://www.henkao.com/wangluo/1274.html 自我总结:https://www.henkao.com/zongjie/2328.html 贫困生助学金申请书:https://www.henkao.com/fanwen/2426.html 关于父爱母爱的作文:https://www.henkao.com/xuexi/1917.html 爸爸生日最朴实的话:https://www.henkao.com/qinggan/789.html 单字id霸气:https://www.henkao.com/wangluo/1583.html 骑鹅旅行记梗概:https://www.henkao.com/xuexi/1804.html 不一样的春节:https://www.henkao.com/zuowen/2271.html 爱国主义演讲稿:https://www.henkao.com/yanjianggao/2672.html 小学五年级数学教学计划:https://www.henkao.com/zhichang/1888.html