PostgreSQL 错误:由于与恢复冲突而取消语句

Posted

技术标签:

【中文标题】PostgreSQL 错误:由于与恢复冲突而取消语句【英文标题】:PostgreSQL ERROR: canceling statement due to conflict with recovery 【发布时间】:2013-01-13 14:03:51 【问题描述】:

在处于待机模式的 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

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

【问题讨论】:

请找到提到这个错误的AWS文档它也有解决方案aws.amazon.com/blogs/database/… 【参考方案1】:

无需触摸hot_standby_feedback。正如其他人所提到的,将其设置为 on 会使 master 膨胀。想象一下在从属设备上打开事务而不是关闭它。

相反,将 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 秒的从站的查询将不会被取消。如果您的工作负载需要更长的查询,只需将这些选项设置为更高的值。

【讨论】:

这是我们最终使用的解决方案。似乎是此处提供的所有选项之间的最佳折衷方案。 这是最好的答案。请注意,根据文档,这些是累积的;如果您在复制副本上有多个查询阻止了复制,那么可能是您到达 899,然后另一个 2 秒的查询被取消。最好在您的代码中实现一些指数回退。此外,流式传输延迟在复制流式传输时生效。如果复制跟不上流式传输,它将转向从存档复制。如果您从存档复制,您可能应该让它赶上,max_standby_archive_delay 可能需要比另一个小。 这仍然是最好的解决方案。请注意,在 Redshift 中,您可以通过参数组设置进行设置,只是它应该在 ms 中,即 900s = 16 分钟 = 900000ms。 要在 GCP 上更新此内容,也在 ms cloud.google.com/sql/docs/postgres/… 中完成 我们有配置(主节点和2个热备节点),所有3个节点都有以下设置:max_standby_archive_delay = 30smax_standby_streaming_delay = 30s,* *hot_standby_feedback = off ** 但是我们面临错误canceling statement due to conflict with recovery 即使对于需要 100ms-2000ms 才能完成的查询(负载测试期间的吞吐量约为 120r/s)为什么即使超时设置为 30s 也会在备用节点上取消短时间运行的查询...?【参考方案2】:

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

更长的查询会更频繁地被取消。

您可以通过在主节点上启动可重复的读取事务来解决此问题,该事务执行虚拟查询,然后在辅助节点上运行真正的查询时处于空闲状态。它的存在将防止清理主节点上的旧行版本。

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

【讨论】:

致 PostgreSQL 9.1+ 的用户:请参阅下面 eradman 的答案以获得实用的解决方案。 对于 PostgreSQL 9.1+ 的用户: max-malysh 的回答要理智得多。除非您了解风险,否则不要执行埃拉德曼的建议。【参考方案3】:

无需在主节点上启动空闲事务。在 postgresql-9.1 中 解决这个问题最直接的方法是设置

hot_standby_feedback = on

这将使 master 知道长时间运行的查询。来自docs:

第一个选项是设置参数hot_standby_feedback,防止 VACUUM 不会删除最近失效的行,因此不会发生清理冲突。

为什么这不是默认值?这个参数是在初始之后添加的 实现,这是备用服务器影响主服务器的唯一方式。

【讨论】:

这个参数应该在standby上设置。 这种情况下master有一些缺点Hot-Standby-Feedback【参考方案4】:

如here 所述,关于hot_standby_feedback = on

嗯,它的缺点是standby会膨胀master, 这也可能让一些人感到惊讶

还有here:

max_standby_streaming_delay 的设置是什么?我宁愿 默认为 -1,而不是默认的 hot_standby_feedback。那样什么 你在standby上做的只会影响standby

所以我加了

max_standby_streaming_delay = -1

我们不会再有pg_dump 错误,也不会出现膨胀 :)

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

【讨论】:

@lennard,这对我有用。我在slave的postgresql.conf中添加了这个配置,然后重启了slave。 当然,您可以通过这种方式获得无限的副本延迟。如果您使用复制槽将副本连接到主服务器,这可能会导致主服务器上过多的 xlog 保留,因此只有在使用 WAL 归档时才真正可行。 如何在 AWS RDS 上设置? @KrisMP 使用 psql 参数组中的@KrisMP - docs.aws.amazon.com/AmazonRDS/latest/UserGuide/…【参考方案5】:

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

select pg_xlog_replay_pause(); -- suspend
select * from foo; -- your query
select pg_xlog_replay_resume(); --resume

【讨论】:

这需要超级用户权限。所以在某些情况下它可能不是一个解决方案。 在 PostgreSQL 10 中,xlog 被替换为wal,所以你想调用pg_wal_replay_pause()pg_wal_replay_resume()【参考方案6】:

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

简而言之,如果你在主服务器上做某事,它需要在从服务器上复制。 Postgres 为此使用 WAL 记录,这些记录在主服务器上的每个记录操作之后发送到从服务器。从机然后执行动作,两者再次同步。在几种情况之一中,您可能会在从站上与 WAL 操作中从主站传入的内容发生冲突。在大多数情况下,slave 上发生的事务与 WAL 操作想要更改的内容相冲突。在这种情况下,您有两种选择:

    将 WAL 操作的应用延迟一点,让从站完成其冲突事务,然后应用该操作。 取消从站上的冲突查询。

我们关心 #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】:

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

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

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

我希望它会有所帮助。

【讨论】:

【参考方案8】:

同样,这是@Artif3x 阐述@max-malysh 的出色答案的第二个警告,两者都在上面。

随着来自主服务器的任何延迟应用事务,追随者将拥有一个较旧的、陈旧的数据视图。因此,虽然通过设置 max_standby_archive_delay 和 max_standby_streaming_delay 为追随者的查询提供完成时间是有意义的,但请记住以下两个警告:

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

如果用于备份的追随者的值最终与托管查询发生太大冲突,则一种解决方案是多个追随者,每个追随者针对一个或另一个进行优化。

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

【讨论】:

以上是关于PostgreSQL 错误:由于与恢复冲突而取消语句的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSQL:单个数据库而不是整个集群的时间点恢复

为啥我的 WorkItem 由于未处理的访问冲突错误而失败?

由于选定行的更新冲突,快照隔离事务中止

错误 VSP1737:由于共享冲突而无法打开文件

出现错误“由于表单未连接而取消表单提交”

git重新关联远程分支