在备用模式下对PostgreSQL db运行查询时,我得到以下错误。导致错误的查询可以正常工作1个月,但当查询超过1个月时,就会出现错误。
ERROR: canceling statement due to conflict with recovery
Detail: User query might have needed to see row versions that must be removed
有什么解决办法吗?谢谢
在备用模式下对PostgreSQL db运行查询时,我得到以下错误。导致错误的查询可以正常工作1个月,但当查询超过1个月时,就会出现错误。
ERROR: canceling statement due to conflict with recovery
Detail: User query might have needed to see row versions that must be removed
有什么解决办法吗?谢谢
在热备服务器上运行查询有点棘手——它可能会失败,因为在查询过程中,一些需要的行可能会在主服务器上更新或删除。由于主服务器不知道查询是在辅助服务器上启动的,所以它认为它可以清理(真空)旧版本的行。然后,secondary必须重播这个清理操作,并且必须强制取消所有可以使用这些行的查询。
较长的查询将更频繁地被取消。
您可以通过在主服务器上启动一个可重复的读事务来解决这个问题,该事务执行一个虚拟查询,然后在辅助服务器上运行一个真正的查询时处于空闲状态。它的存在将防止主目录上的旧行版本被清空。
文档中的“热备-处理查询冲突”一节详细介绍了这个主题和其他解决方法。
不需要在主服务器上启动空闲事务。在postgresql-9.1中 解决这个问题最直接的方法就是设置
hot_standby_feedback = on
这将使主服务器知道长时间运行的查询。从文档中可以看出:
第一个选项是设置参数hot_standby_feedback,这可以防止 从删除最近死亡的行中进行VACUUM,因此不会发生清理冲突。
为什么这不是默认的?该参数添加在初始值之后 实现,这是备用服务器影响主服务器的唯一方式。
正如这里所说的关于hot_standby_feedback = on:
它的缺点是备用电脑会让主电脑膨胀, 这可能也会让一些人感到惊讶
在这里:
max_standby_streaming_delay的设置是什么?我宁愿 默认为-1,而不是默认的hot_standby_feedback。那样的话 你在待机时做的事只会影响待机
所以我补充道
max_standby_streaming_delay = -1
和没有更多的pg_dump错误为我们,也不是主膨胀:)
对于AWS RDS实例,请查看http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.html
当一个长时间运行的查询正在运行时,热备从服务器上的表数据被修改。确保表数据不被修改的一个解决方案(PostgreSQL 9.1+)是暂停复制并在查询后恢复:
select pg_xlog_replay_pause(); -- suspend
select * from foo; -- your query
select pg_xlog_replay_resume(); --resume
不需要触摸hot_standby_feedback。正如其他人所提到的,将其设置为开启会导致腹胀。想象一下在一个slave上打开一个事务,而不是关闭它。
相反,将max_standby_archive_delay和max_standby_streaming_delay设置为一个合理的值:
# /etc/postgresql/10/main/postgresql.conf on a slave
max_standby_archive_delay = 900s
max_standby_streaming_delay = 900s
这样,对于持续时间小于900秒的slave的查询将不会被取消。如果您的工作负载需要更长的查询,只需将这些选项设置为更高的值。
也许现在回答这个问题已经太迟了,但我们在制作过程中也面临着同样的问题。 之前我们只有一个RDS,随着应用端用户数量的增加,我们决定为它添加Read Replica。Read副本在登台时工作正常,但一旦我们转移到生产时,我们开始得到相同的错误。
所以我们通过在Postgres属性中启用hot_standby_feedback属性来解决这个问题。 我们参考了以下链接
https://aws.amazon.com/blogs/database/best-practices-for-amazon-rds-postgresql-replication/
我希望它能有所帮助。
我将添加一些更新的信息和参考@max-malysh的精彩回答。
In short, if you do something on the master, it needs to be replicated on the slave. Postgres uses WAL records for this, which are sent after every logged action on the master to the slave. The slave then executes the action and the two are again in sync. In one of several scenarios, you can be in conflict on the slave with what's coming in from the master in a WAL action. In most of them, there's a transaction happening on the slave which conflicts with what the WAL action wants to change. In that case, you have two options:
将WAL操作的应用延迟一点,允许从服务器完成其冲突事务,然后应用该操作。 取消从机上冲突的查询。
我们关心的是#1和两个值:
max_standby_archive_delay——当从WAL存档(不是当前数据)中读取数据时,在主服务器和从服务器长时间断开连接后使用的延迟。 max_standby_streaming_delay -通过流复制接收WAL条目时用于取消查询的延迟。
Generally, if your server is meant for high availability replication, you want to keep these numbers short. The default setting of 30000 (milliseconds if no units given) is sufficient for this. If, however, you want to set up something like an archive, reporting- or read-replica that might have very long-running queries, then you'll want to set this to something higher to avoid cancelled queries. The recommended 900s setting above seems like a good starting point. I disagree with the official docs on setting an infinite value -1 as being a good idea--that could mask some buggy code and cause lots of issues.
关于长时间运行的查询并将这些值设置得更高的一个注意事项是,在slave上与长时间运行的查询并行运行的其他查询将会看到旧数据,直到长时间查询完成。开发人员需要理解这一点,并序列化不应该同时运行的查询。
关于max_standby_archive_delay和max_standby_streaming_delay如何工作以及为什么工作的完整解释,请访问这里。
同样,对于@max-malysh的精彩回答,这里还有第二个警告。
对于来自主服务器的事务的任何延迟应用程序,从者将拥有一个旧的、过时的数据视图。因此,虽然通过设置max_standby_archive_delay和max_standby_streaming_delay为追随者上的查询提供时间是有意义的,但要记住这两个注意事项:
追随者作为备用/备份的价值会降低 在追随者上运行的任何其他查询都可能返回过时的数据。
如果用于备份的关注者的值最终与托管查询冲突太多,那么一种解决方案是多个关注者,每个关注者都针对其中一个进行了优化。
另外,请注意,一行中的多个查询可能会导致wal条目的应用程序一直被延迟。因此,在选择新值时,不只是单个查询的时间,而是在冲突查询开始时启动一个移动窗口,并在wal条目最终应用时结束。