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_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 秒的从站的查询将不会被取消。如果您的工作负载需要更长的查询,只需将这些选项设置为更高的值。
【讨论】:
这是我们最终使用的解决方案。似乎是此处提供的所有选项之间的最佳折衷方案。 这是最好的答案。请注意,根据文档,这些是累积的;如果您在复制副本上有多个查询阻止了复制,那么可能是您到达 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 = 30s,max_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_delay
和max_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 错误:由于与恢复冲突而取消语句的主要内容,如果未能解决你的问题,请参考以下文章