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

AnA*_*ice 119 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
Run Code Online (Sandbox Code Playgroud)

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

Tom*_*zky 77

在热备用服务器上运行查询有点棘手 - 它可能会失败,因为在查询期间,某些所需的行可能会在主服务器上更新或删除.由于主服务器不知道在辅助服务器上启动查询,因此认为它可以清理(真空)旧版本的行.然后,secondary必须重放此清理,并且必须强制取消所有可以使用这些行的查询.

更长时间的查询将被取消.

您可以通过在primary上启动可重复读取事务来执行此操作,该事务执行虚拟查询,然后在辅助节点上运行实际查询时处于空闲状态.它的存在将防止对主要版本的旧行版本进行真空吸尘.

有关此主题和其他解决方法的更多信息,请参阅文档中的Hot Standby - Handling Query Conflicts部分.

  • 对于PostgreSQL 9.1+的用户:请参阅下面的**eradman**的答案,以获得实用的解决方案. (9认同)
  • 对于PostgreSQL 9.1+的用户:max-malysh的答案要明智得多。除非您了解风险,否则请勿执行擦除建议。 (2认同)

era*_*man 74

无需在主服务器上启动空闲事务.在postgresql-9.1中,解决此问题的最直接方法是设置

hot_standby_feedback = on
Run Code Online (Sandbox Code Playgroud)

这将使主人知道长时间运行的查询.来自文档:

第一个选项是设置参数hot_standby_feedback,这会阻止VACUUM删除最近死的行,因此不会发生清除冲突.

为什么这不是默认值?初始实现后添加了此参数,这是备用数据库影响主服务器的唯一方法.

  • 应该在备用数据库上设置此参数. (10认同)
  • 检查我的回答,这似乎不是一个好习惯 (4认同)
  • [网络存档链接](http://web.archive.org/web/20150324004227/http://postgresql.nabble.com/Hot-Standby-Feedback-should-default-to-on-in-9-3- td5734379.html)@EvgenyLiskovets 评论中的链接。 (3认同)
  • 在这种情况下,master有一些缺点[Hot-Standby-Feedback](http://postgresql.nabble.com/Hot-Standby-Feedback-should-default-to-on-in-9-3-td5734379.html ) (2认同)

Max*_*ysh 70

无需触摸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
Run Code Online (Sandbox Code Playgroud)

这样,持续时间小于900秒的从站查询将不会被取消.如果您的工作负载需要更长的查询,请将这些选项设置为更高的值.

  • 这是最好的答案。请注意,根据文档,这些是累积的;如果您在副本上有多个查询阻止复制,那么您可能会到达 899,然后另一个 2 秒的查询被取消。最好在您的代码中实现一些指数回退。此外,流式传输延迟在复制流式传输时有效。如果复制跟不上流式传输,它将转向从存档复制。如果您从存档复制,您可能应该让它赶上,`max_standby_archive_delay` 可能需要比另一个小。 (4认同)
  • 我将 RDS 与只读副本一起使用 - 我的查询被取消。要使其正常工作: - 您需要创建一个新参数组 - 更改新参数组中“max_standby_archive_delay”和“max_standby_streaming_delay”的值 - 修改实例或副本以拥有新参数组 - 重新启动实例以申请。链接 https://forums.aws.amazon.com/thread.jspa?messageID=943196&tstart=0 (4认同)
  • 这仍然是这里最好的解决方案。请注意,在 Redshift 中,您可以通过参数组设置来设置它,但它应该以 `ms` 为单位,即 900s = 16 分钟 = 900000ms。 (3认同)
  • 我们有配置(主节点和 2 个热备用节点),所有 3 个节点都有以下设置: **max_standby_archive_delay = 30s**,**max_standby_streaming_delay = 30s**,**hot_standby_feedback = off ** 但我们面临错误`取消语句由于与恢复冲突,即使对于需要 100ms-2000ms 才能完成的查询(负载测试期间的吞吐量 ~120r/s),为什么即使超时设置为 30s,在备用节点上短时间运行的查询也会被取消......? (3认同)
  • 要在 GCP 上更新此内容,也在 `ms` https://cloud.google.com/sql/docs/postgres/flags?hl=en_US&_ga=2.48390694.-1061973720.1536093593 中完成 (2认同)
  • @ErikasNeverdauskas也许这会回答你的问题“请注意,max_standby_archive_delay与取消之前查询可以运行的最大时间长度不同;相反,它是允许应用任何一个WAL段数据的最大总时间。因此,如果一个查询有导致 WAL 段早期的显着延迟,后续冲突查询的宽限时间将少得多。” 摘自 [pg 文档](https://www.postgresql.org/docs/12/runtime-config-replication.html) (2认同)

Gil*_*not 48

如前所述这里hot_standby_feedback = on:

好吧,它的缺点是备用数据库可能使主人膨胀,这对一些人来说也许是令人惊讶的

在这里:

使用max_standby_streaming_delay的设置?我宁愿默认为-1而不是默认的hot_standby_feedback.这样,您在备用数据库上执行的操作只会影响备用数据库


所以我补充道

max_standby_streaming_delay = -1
Run Code Online (Sandbox Code Playgroud)

pg_dump对我们来说没有更多的错误,也没有主人臃肿:)

对于AWS RDS实例,请查看http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.html

  • 当然,你可以通过这种方式获得无限复制品.如果您使用复制槽将副本连接到主服务器,这可能会导致主服务器上的xlog保留过多,因此,如果您使用WAL存档,它实际上是可行的. (13认同)
  • 如何在AWS RDS上设置此项? (6认同)
  • 参数组中的@KrisMP - http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.html (4认同)

小智 11

在长时间运行的查询运行时,将修改热备用从属服务器上的表数据.确保表数据不被修改的解决方案(PostgreSQL 9.1+)是在查询后暂停复制并恢复:

select pg_xlog_replay_pause(); -- suspend
select * from foo; -- your query
select pg_xlog_replay_resume(); --resume
Run Code Online (Sandbox Code Playgroud)

  • 在 PostgreSQL 10 中,`xlog` 被替换为 `wal`,因此你需要调用 `pg_wal_replay_pause()` 和 `pg_wal_replay_resume()`。 (4认同)
  • 这需要超级用户权限。所以在某些情况下它可能不是解决方案。 (2认同)

Art*_*f3x 8

我将添加一些更新的信息和对@max-malysh 上面的优秀答案的引用。

总之,如果你在master上做了什么,就需要在slave上进行复制。Postgres 为此使用 WAL 记录,这些记录在 master 上的每个记录的操作之后发送到 slave。然后从站执行操作,两者再次同步。在几种情况之一中,您可能会在从站上与 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工作,所以,去这里


Tus*_*r.k 5

答案可能为时已晚,但我们在生产中面临同样的问题。之前我们只有一个RDS,随着应用端用户数量的增加,我们决定为其添加只读副本。只读副本在暂存时正常工作,但是一旦我们转移到生产中,我们就会开始遇到相同的错误。

所以我们通过在 Postgres 属性中启用hot_standby_feedback属性来解决这个问题。我们参考了以下链接

https://aws.amazon.com/blogs/database/best-practices-for-amazon-rds-postgresql-replication/

我希望它会有所帮助。