我按照这个答案NOT NULL
向包含约 100M 行的现有数据库表添加约束。但是,当我尝试运行后端进程时,会取出一个ShareLock
.
ALTER TABLE mytable VALIDATE CONSTRAINT myfield_not_null;
pg_locks
我通过检查另一个会话来确认这一点,在其中我可以看到以下内容(5447 是尝试验证约束的后端的 pid):
mydb=> select l.pid, l.mode, l.granted, l.waitstart, a.xact_start, a.query_start, a.state from pg_locks l join pg_stat_activity a on l.pid = a.pid;
pid | mode | granted | waitstart | xact_start | query_start | state
-------+--------------------------+---------+-------------------------------+-------------------------------+-------------------------------+--------
5447 | ShareLock | t | | 2023-10-06 14:58:23.133136+00 | 2023-10-06 14:58:23.355743+00 | active
5447 | ShareUpdateExclusiveLock | t | | 2023-10-06 14:58:23.133136+00 | 2023-10-06 14:58:23.355743+00 | active
文档明确指出:
可以发出 VALIDATE CONSTRAINT 命令来验证现有行是否满足约束。验证步骤不需要锁定并发更新,因为它知道其他事务将对它们插入或更新的行强制执行约束;仅需要检查预先存在的行。因此,验证仅获取正在更改的表上的 SHARE UPDATE EXCLUSIVE 锁。
ShareLock 阻止了一些需要 RowExclusiveLock(更新/插入/删除)的查询。
如何在不使用 ShareLock 的情况下验证约束?
AWS 确认这是他们的 postgres 版本的问题。我猜他们做了某种内部修补并搞砸了。支持人员确认此行为存在于版本 14.7 和 14.8 上,但不存在于 14.6 或 14.9 上