208

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

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

4

8 回答 8

152

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

于 2017-12-05T19:33:42.043 回答
126

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

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

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

有关此主题和其他解决方法的更多信息,请参阅文档中的Hot Standby — 处理查询冲突部分。

于 2013-01-29T23:51:54.830 回答
88

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

hot_standby_feedback = on

这将使 master 知道长时间运行的查询。从文档

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

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

于 2014-02-10T19:34:59.283 回答
56

如此所述:hot_standby_feedback = on

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

这里:

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

于 2015-10-22T13:58:34.247 回答
17

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

select pg_xlog_replay_pause(); -- suspend
select * from foo; -- your query
select pg_xlog_replay_resume(); --resume
于 2017-10-05T08:56:02.463 回答
9

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

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

  1. 将 WAL 动作的应用延迟一点,让从机完成其冲突事务,然后应用该动作。
  2. 取消slave上的冲突查询。

我们关心 #1 和两个值:

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

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

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

有关如何max_standby_archive_delaymax_standby_streaming_delay工作以及为什么的完整说明,请转到此处

于 2020-02-19T16:18:06.243 回答
5

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

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

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

我希望它会有所帮助。

于 2020-02-16T05:14:50.767 回答
2

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

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

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

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

于 2020-03-30T16:39:57.973 回答