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


139

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

Answers:


89

在热备用服务器上运行查询有些棘手-可能会失败,因为在查询过程中某些需要的行可能在主数据库上被更新或删除。作为主数据库,它不知道查询是在辅助数据库上启动的,因此认为它可以清除(清理)其行的旧版本。然后,secondary必须重播此清理操作,并且必须强制取消所有可以使用这些行的查询。

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

您可以通过在主数据库上启动可重复的读取事务来解决此问题,该事务将执行虚拟查询,然后在次要数据库上运行实际查询时处于空闲状态。它的存在将防止在主数据库上清除旧行版本。

文档的“ 热备-处理查询冲突”部分介绍了有关此主题的更多信息以及其他解决方法。


10
对于PostgreSQL 9.1+的用户:请参阅下面的eradman的答案以获取实用的解决方案。
佐尔坦

3
对于PostgreSQL 9.1+的用户:max-malysh的答案要明智得多。除非您了解风险,否则请勿执行擦除建议。
达沃斯

91

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


1
这是我们最终使用的解决方案。似乎是此处介绍的所有选项之间的最佳折衷。
mohit6up

2
这是最好的答案。请注意,根据文档,这些是累积的;如果您对复制副本有多个查询来阻止复制,则可能是到899,然后又取消了2秒查询。最好只是在代码中实现一些指数补偿。同样,在复制正在流式传输时,流式传输延迟有效。如果复制跟不上流,它将从存档复制到复制。如果要从存档中复制,则可能会让它追上来,max_standby_archive_delay可能需要小于另一个。
达沃斯

2
这仍然是最好的解决方案。请注意,在Redshift中,您可以通过参数组设置进行设置,只有它应该在ms,即900s = 16分钟= 900000ms。
NullDev

要在GCP上对此进行更新,也可以在ms cloud.google.com/sql/docs/postgres/…中
howMuchCheeseIsTooMuchCheese

如果备用数据库的目的是例如进行报告,并且它不是需要准备进行故障转移的热备用数据库,那么这绝对是最佳答案。
soupdog

77

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

hot_standby_feedback = on

这将使主服务器知道长时间运行的查询。从文档

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

为什么这不是默认值?此参数是在初始实现后添加的,这是备用数据库可以影响主数据库的唯一方法。


11
此参数应在备用数据库上设置。
史蒂夫·凯莱特

3
在这种情况下,主服务器有一些缺点热备反馈
Evgeny Liskovets

50

如前所述这里hot_standby_feedback = on

好吧,它的缺点是备用数据库可能会使主数据库膨胀,这对于某些人来说也可能会感到惊讶

在这里

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


所以我加了

max_standby_streaming_delay = -1

而且pg_dump对我们来说没有更多错误,也没有膨胀:)

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


1
@lennard,这对我有用。我在从服务器的postgresql.conf中添加了此配置,然后重新启动了从服务器。
Ardee Aram

13
当然,您可以通过这种方式获得无限的副本滞后。而且,如果您使用复制插槽将副本连接到主服务器,则可能导致主服务器上的xlog保留过多,因此,仅当您使用WAL归档时,这才切实可行。
Craig Ringer

7
如何在AWS RDS上进行设置?
克里斯·MP

1
@KrisMP使用psql
Yehonatan


13

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

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

1
这需要超级用户权限。因此,在某些情况下可能不是解决方案。
Joao Baltazar '18

1
在PostgreSQL 10中,xlog被替换为wal,因此您要调用pg_wal_replay_pause()pg_wal_replay_resume()
womble

3

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

因此,我们通过在Postgres属性中启用hot_standby_feedback属性来解决此问题。我们引用了以下链接

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

希望对您有所帮助。


2

我将添加一些更新的信息和对@ 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工作,所以,去这里


1

同样,以上是@ Artif3x对@ max-malysh出色答案的详细说明。

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

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.