在待机模式下在PostgreSQL数据库上运行查询时出现以下错误。导致错误的查询在1个月内正常工作,但是当您查询超过1个月时,会出现错误。
ERROR: canceling statement due to conflict with recovery
Detail: User query might have needed to see row versions that must be removed
有关如何解决的任何建议?感谢
答案 0 :(得分:68)
在热备用服务器上运行查询有点棘手 - 它可能会失败,因为在查询期间,某些所需的行可能会在主服务器上更新或删除。由于主服务器不知道在辅助服务器上启动查询,因此认为它可以清理(真空)旧版本的行。然后,secondary必须重放此清理,并且必须强制取消所有可以使用这些行的查询。
更长时间的查询会被取消。
您可以通过在primary上启动可重复读取事务来解决此问题,该事务执行虚拟查询,然后在辅助节点上运行实际查询时处于空闲状态。它的存在将防止对主要版本的旧行版本进行抽真空。
有关此主题的更多信息以及其他解决方法在文档的Hot Standby — Handling Query Conflicts部分进行了解释。
答案 1 :(得分:66)
无需在主服务器上启动空闲事务。在postgresql-9.1中 解决这个问题最直接的方法是设置
hot_standby_feedback = on
这将使主人知道长时间运行的查询。来自docs:
第一个选项是设置参数hot_standby_feedback,这会阻止 VACUUM可以删除最近死行,因此不会发生清理冲突。
为什么这不是默认值?此参数在初始后添加 实现,这是备用数据库影响主服务器的唯一方法。
答案 2 :(得分:46)
无需触碰hot_standby_feedback
。正如其他人所提到的那样,将其设置为on
可能会让人失望。想象一下,在奴隶上打开交易而不是关闭它。
相反,请将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秒的从站的查询将不会被取消。如果您的工作负载需要更长的查询,只需将这些选项设置为更高的值。
答案 3 :(得分:44)
如here所述hot_standby_feedback = on
:
嗯,它的缺点是备用数据库会使主机膨胀, 这对某些人来说可能会让人感到惊讶
here:
使用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
答案 4 :(得分:8)
在长时间运行的查询运行时,将修改热备用从属服务器上的表数据。确保表数据不被修改的解决方案(PostgreSQL 9.1+)是在查询后暂停复制并恢复:
select pg_xlog_replay_pause(); -- suspend
select * from foo; -- your query
select pg_xlog_replay_resume(); --resume
答案 5 :(得分:5)
答案可能为时已晚,但我们在制作中遇到同样的问题。 之前我们只有一个RDS,随着应用程序方面用户数量的增加,我们决定为其添加只读副本。只读副本在登台上可以正常工作,但是一旦移至生产环境,我们就会开始遇到相同的错误。
因此,我们通过在Postgres属性中启用 hot_standby_feedback 属性来解决此问题。 我们引用了以下链接
https://aws.amazon.com/blogs/database/best-practices-for-amazon-rds-postgresql-replication/
我希望这会有所帮助。
答案 6 :(得分:3)
我将添加一些更新的信息以及上面@ max-malysh出色答案的引用。
简而言之,如果您在主服务器上执行某些操作,则需要将其复制到从服务器上。 Postgres为此使用WAL记录,这些记录在主服务器上的每个已记录操作之后发送到从属服务器。然后,从站执行该动作,并且两者再次同步。在几种情况之一中,您可能会在从属服务器上与WAL动作中来自主服务器的内容发生冲突。在大多数情况下,在从属服务器上发生了与WAL动作想要更改的事务发生冲突的事务。在这种情况下,您有两个选择:
我们关注#1和两个值:
max_standby_archive_delay
-这是从WAL归档文件(不是当前数据)中读取数据后,主服务器和从服务器之间长时间断开连接后使用的延迟。max_standby_streaming_delay
-通过流复制接收到WAL条目时用于取消查询的延迟。通常,如果您的服务器用于高可用性复制,则希望保持这些数字简短。 30000
的默认设置(如果没有给出单位,则为毫秒)就可以满足此要求。但是,如果您想设置诸如存档,报告或只读副本之类的查询,这些查询可能运行时间很长,那么您需要将其设置为更高的值,以避免查询被取消。上面推荐的900s
设置似乎是一个很好的起点。我不同意将无限值-1
设置为一个好主意的官方文档,因为这可能会掩盖一些错误代码并引起很多问题。
关于长时间运行的查询并将这些值设置为更高的一个警告是,在从属服务器上与长时间运行的查询并行运行的其他查询(导致WAL动作被延迟)将看到旧数据,直到长时间查询为止完成。开发人员将需要理解这一点并序列化不应同时运行的查询。
要详细了解max_standby_archive_delay
和max_standby_streaming_delay
的工作原理以及原因,请go here。
答案 7 :(得分:2)
同样,这是@ Artif3x关于@ max-malysh出色答案的第二个警告,
如果主服务器延迟应用交易,则跟随者将拥有较旧的旧数据视图。因此,在通过设置max_standby_archive_delay和max_standby_streaming_delay为跟随者提供查询时间的同时,请注意以下两个注意事项:
如果备份的跟随者的价值最终与托管查询发生冲突,那么一种解决方案将是多个跟随者,每个跟随者针对一个或另一个进行优化。
此外,请注意,连续几个查询可能会导致wal条目的应用不断延迟。因此,在选择新值时,不仅是一次查询的时间,而且是一个移动的窗口,它会在有冲突的查询开始时开始,并在最终应用wal条目时结束。