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

93ze6v8z  于 2023-05-17  发布在  PostgreSQL
关注(0)|答案(8)|浏览(266)

在备用模式下对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

有什么解决办法吗?谢谢

wwtsj6pe

wwtsj6pe1#

不需要触摸hot_standby_feedback。正如其他人所提到的,将其设置为on会使master膨胀。想象一下,在一个slave上打开一个事务,而不是关闭它。
相反,将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秒的从服务器上的查询将不会被取消。如果您的工作负载需要更长的查询时间,只需将这些选项设置为更高的值。
postgres文档对此进行了详细的讨论。那里的关键建议是:
如果备用服务器用于执行长时间运行的查询,则最好使用高延迟值甚至无限延迟值[在max_standby_archive_delaymax_standby_streaming_delay中]

用户应该清楚,主服务器上定期大量更新的表将很快导致备用服务器上运行较长时间的查询被取消。在这种情况下,可以认为max_standby_archive_delay或max_standby_streaming_delay的有限值的设置类似于设置statement_timeout。
您还可以考虑将vacuum_defer_cleanup_age(on the primary)与最大待机延迟组合设置。正如docs所说:
另一个选择是增加主服务器上的vacuum_defer_cleanup_age,这样死行就不会像正常情况下那样被清理得那么快。这将允许查询在备用服务器上取消之前有更多的时间执行,而不必设置一个高的max_standby_streaming_delay

5fjcxozz

5fjcxozz2#

在热备用服务器上运行查询有些棘手-它可能会失败,因为在查询过程中,主服务器上的一些所需行可能会被更新或删除。由于主服务器不知道查询是在辅助服务器上启动的,因此它认为可以清理(真空)其行的旧版本。然后,辅助服务器必须重播此清理,并且必须强制取消可以使用这些行的所有查询。
较长的查询将更频繁地被取消。
您可以通过在主服务器上启动一个可重复的读事务来解决这个问题,该事务执行一个伪查询,然后在备用服务器上运行一个真实的的查询时处于空闲状态。它的存在将阻止清除主服务器上的旧行版本。
有关此主题和其他解决方法的更多信息,请参见文档中的“热备份-处理查询冲突”部分。

hgncfbus

hgncfbus3#

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

hot_standby_feedback = on

这将使master知道长时间运行的查询。关于docs
第一个选项是设置参数hot_standby_feedback,这将防止VACUUM删除最近失效的行,从而不会发生清理冲突。
为什么这不是默认值?这个参数是在初始实现之后添加的,它是备用设备影响主设备的唯一方式。

xurqigkl

xurqigkl4#

关于hot_standby_feedback = on
好吧,它的缺点是备用可以膨胀的主,这可能是令人惊讶的一些人,太
这里:
max_standby_streaming_delay的设置是什么?我宁愿默认为-1,而不是默认hot_standby_feedback。那样的话你在备用机上所做的只会影响备用机
所以我加了一句

max_standby_streaming_delay = -1

而且对我们来说没有更多的pg_dump错误,也没有master bloat:)
对于AWS RDS示例,请选中http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.html

omjgkv6w

omjgkv6w5#

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

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

w1jd8yoj6#

我将为@max-malysh上面的优秀答案添加一些更新的信息和参考资料。
简而言之,如果你在主服务器上做了一些事情,它需要在从服务器上复制。Postgres为此使用WAL记录,这些记录在master上的每个日志操作之后发送到slave。然后从设备执行动作,两者再次同步。在以下几种情况中的一种情况下,您可能会在从服务器上与WAL操作中来自主服务器的内容发生冲突。在大多数情况下,在从服务器上发生的事务与WAL动作想要更改的内容相冲突。在这种情况下,您有两个选择:
1.将WAL操作的应用延迟一点,允许从机完成其冲突事务,然后应用该操作。
1.取消从机上的冲突查询。
我们关注的是#1和两个值:

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

通常,如果您的服务器是用于高可用性复制的,您希望保持这些数字较短。默认设置30000(如果没有给出单位,则为毫秒)就足够了。但是,如果您要设置可能具有长时间运行的查询的归档、报告或读取副本,则需要将此设置为更高的值,以避免取消查询。上面推荐的900s设置似乎是一个很好的起点。我不同意官方文档中关于设置无限值-1是一个好主意的观点--这可能会掩盖一些错误代码并导致许多问题。
关于长时间运行的查询和将这些值设置得更高的一个警告是,与导致WAL操作延迟的长时间运行的查询并行运行的从机上的其他查询将看到旧数据,直到长时间查询完成。开发人员需要理解这一点,并序列化不应该同时运行的查询。
有关max_standby_archive_delaymax_standby_streaming_delay如何工作以及为什么工作的完整解释,请访问此处。

1l5u6lss

1l5u6lss7#

现在给出答案可能为时已晚,但我们在生产方面也面临着同样的问题。之前我们只有一个RDS,随着应用端用户数量的增加,我们决定为其添加读取副本。读取复制副本在转移上工作正常,但一旦我们移动到生产,我们就开始收到相同的错误。
所以我们通过在Postgres属性中启用hot_standby_feedback属性来解决这个问题。我们参考了以下链接
https://aws.amazon.com/blogs/database/best-practices-for-amazon-rds-postgresql-replication/
我希望这会有所帮助。

omvjsjqw

omvjsjqw8#

同样,这里是对@Artif3x对@max-malysh的优秀回答的第二个警告,两者都在上面。
对于来自主服务器的事务的任何延迟应用,跟随服务器将具有较旧的、陈旧的数据视图。因此,在通过设置max_standby_archive_delay和max_standby_streaming_delay为follower上的查询提供完成时间时,请记住以下两个警告:

  • 跟随者作为备用/备份的价值减小
  • 在follower may return stale data上运行的任何其他查询。

如果用于备份的follower的值最终与托管查询冲突太多,一个解决方案将是多个follower,每个follower针对一个或另一个进行优化。
另外,请注意,一行中的几个查询可能会导致wal条目的应用持续延迟。因此,当选择新值时,它不仅仅是单个查询的时间,而是一个移动窗口,每当有冲突的查询开始时就开始,当最终应用wal条目时结束。

相关问题