我们正在运行 AWS Aurora PostgreSQL 版本 13 数据库。有一天,我试图设置一个备份作业从只读副本运行,最终遇到了错误“用户持有关系锁的时间太长”。我使用这个问题的答案解决了这个问题。
我的问题是理论上的,如果这听起来很愚蠢,请原谅我,但我在这里遗漏了一些东西。如果 Postgres 有 MVCC 而不是锁定,为什么 pg_dump 会关心用户“锁定”另一个关系?难道不应该只读取该行的最后一个版本吗?
我们正在运行 AWS Aurora PostgreSQL 版本 13 数据库。有一天,我试图设置一个备份作业从只读副本运行,最终遇到了错误“用户持有关系锁的时间太长”。我使用这个问题的答案解决了这个问题。
我的问题是理论上的,如果这听起来很愚蠢,请原谅我,但我在这里遗漏了一些东西。如果 Postgres 有 MVCC 而不是锁定,为什么 pg_dump 会关心用户“锁定”另一个关系?难道不应该只读取该行的最后一个版本吗?
这是关于表锁和流复制冲突的。
pg_dump
必须读取表,而读取表需要ACCESS SHARE
对该表加锁。此类锁定仅与诸如DROP TABLE
、TRUNCATE
、CLUSTER
和VACUUM (FULL)
的某些变体之类的活动发生冲突ALTER TABLE
。锁ACCESS SHARE
不会阻止写入者,它会防止并发会话删除您当前正在读取的数据文件。现在,如果您
pg_dump
在备用数据库上有一个长时间运行的查询,并且有人TRUNCATE
在主数据库上创建了表,PostgreSQL 将尝试ACCESS EXCLUSIVE
在备用数据库上重放该语句和关联的锁。这将与长时间运行的查询发生冲突,如果在过去pg_dump
之后没有完成max_standby_streaming_delay
,则查询将被取消并pg_dump
以错误终止。请注意,冲突不一定与上述语句之一有关:如果 autovacuum 处理主数据库上的表,并且表中的最后几页变为空,则将尝试删除这些页,这也需要对主数据库进行
VACUUM
短暂ACCESS EXCLUSIVE
锁定桌子。这不会中断主数据库上的处理,但可能会导致备用数据库上的查询被取消。在备用服务器上设置
max_standby_streaming_delay
为 -1 以避免出现问题。这是一篇更详细地处理该问题的文章。