PostgreSQL错误:由于与恢复冲突而取消声明

时间:2013-01-29 21:15:23

标签: postgresql postgresql-9.1

在待机模式下在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

有关如何解决的任何建议?感谢

8 个答案:

答案 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_delaymax_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. 将WAL动作的应用延迟一会儿,让从属服务器完成其冲突的事务,然后应用该动作。
  2. 取消从属服务器上的冲突查询。

我们关注#1和两个值:

  • max_standby_archive_delay-这是从WAL归档文件(不是当前数据)中读取数据后,主服务器和从服务器之间长时间断开连接后使用的延迟。
  • max_standby_streaming_delay-通过流复制接收到WAL条目时用于取消查询的延迟。

通常,如果您的服务器用于高可用性复制,则希望保持这些数字简短。 30000的默认设置(如果没有给出单位,则为毫秒)就可以满足此要求。但是,如果您想设置诸如存档,报告或只读副本之类的查询,这些查询可能运行时间很长,那么您需要将其设置为更高的值,以避免查询被取消。上面推荐的900s设置似乎是一个很好的起点。我不同意将无限值-1设置为一个好主意的官方文档,因为这可能会掩盖一些错误代码并引起很多问题。

关于长时间运行的查询并将这些值设置为更高的一个警告是,在从属服务器上与长时间运行的查询并行运行的其他查询(导致WAL动作被延迟)将看到旧数据,直到长时间查询为止完成。开发人员将需要理解这一点并序列化不应同时运行的查询。

要详细了解max_standby_archive_delaymax_standby_streaming_delay的工作原理以及原因,请go here

答案 7 :(得分:2)

同样,这是@ Artif3x关于@ max-malysh出色答案的第二个警告,

如果主服务器延迟应用交易,则跟随者将拥有较旧的旧数据视图。因此,在通过设置max_standby_archive_delay和max_standby_streaming_delay为跟随者提供查询时间的同时,请注意以下两个注意事项:

  • 跟随者作为备用/备份的价值降低
  • 在关注者may return stale data上运行的任何其他查询。

如果备份的跟随者的价值最终与托管查询发生冲突,那么一种解决方案将是多个跟随者,每个跟随者针对一个或另一个进行优化。

此外,请注意,连续几个查询可能会导致wal条目的应用不断延迟。因此,在选择新值时,不仅是一次查询的时间,而且是一个移动的窗口,它会在有冲突的查询开始时开始,并在最终应用wal条目时结束。