PostgreSQL 18 中文参考文档(未翻译部分保留英文)🌐 切换到英文原版 →

13.3. 显式锁定 #

13.3.1. 表级锁
13.3.2. 行级锁
13.3.3. 页级锁
13.3.4. 死锁
13.3.5. 咨询锁

PostgreSQL 提供了多种不同级别的锁模式,用于精确控制并发数据访问。在执行绝大多数 SQL 命令时,系统会自动申请相应模式的物理锁,以确保在命令执行期间被引用的数据表不会被并发 DDL 销毁或修改。

可以通过系统视图 pg_locks 实时监控当前服务端正在持有的所有未决锁信息。

13.3.1. 表级锁 #

使用 LOCK 可以显式为整张表加锁。核心表级锁模式按冲突严苛程度递增如下:

表级锁模式

ACCESS SHARE

仅与 ACCESS EXCLUSIVE 冲突。任何纯只读查询(SELECT)都会自动在目标表上获取该锁。

ROW SHARE

由带有 FOR UPDATE 或 FOR SHARE 的查询自动获取。

ROW EXCLUSIVE

由修改表内数据的命令(UPDATE、DELETE、INSERT 与 MERGE)自动获取。

SHARE UPDATE EXCLUSIVE

保护数据表免受并发模式变更及并发 VACUUM 干扰。由常规 VACUUM、ANALYZE 与 CREATE INDEX CONCURRENTLY 获取。

SHARE

保护数据表免受并发数据写入修改。由常规 CREATE INDEX 获取。

SHARE ROW EXCLUSIVE

自排他锁,由部分表结构定义修改命令自动获取。

EXCLUSIVE

阻断并发写入与并发读取,仅允许并发的只读查询。

ACCESS EXCLUSIVE

最高等级完全排他锁,与所有其他锁模式完全冲突。由 ALTER TABLE、DROP TABLE、TRUNCATE 等命令自动获取。

Table 13.2. 表锁冲突矩阵

请求的锁模式当前已持有的锁模式
ACCESS SHAREROW SHAREROW EXCL.SHARE UPDATE EXCL.SHARESHARE ROW EXCL.EXCL.ACCESS EXCL.
ACCESS SHARE       X
ROW SHARE      XX
ROW EXCLUSIVE    XXXX
SHARE UPDATE EXCLUSIVE   XXXXX
SHARE  XX XXX
SHARE ROW EXCLUSIVE  XXXXXX
EXCLUSIVE XXXXXXX
ACCESS EXCLUSIVEXXXXXXXX

13.3.2. 行级锁 #

行级锁用于控制并发写操作对具体数据行的竞争,完全不影响只读查询。核心行级锁包括:

  • FOR UPDATE:独占排他行锁。阻止其他事务修改、删除或锁定这些行。由 DELETE 以及更新关键索引列的 UPDATE 自动获取。

  • FOR NO KEY UPDATE:弱排他行锁。不修改主外键索引列的普通 UPDATE 自动获取,允许其他事务并发执行 FOR KEY SHARE。

  • FOR SHARE:共享读行锁。阻止其他事务修改或删除该行,但允许并发共享读取。

  • FOR KEY SHARE:外键检查行锁。在外键关联检查时自动获取,允许并发更新非关键字段。

Table 13.3. 行锁冲突矩阵

请求的锁模式当前已持有的锁模式
FOR KEY SHAREFOR SHAREFOR NO KEY UPDATEFOR UPDATE
FOR KEY SHARE   X
FOR SHARE  XX
FOR NO KEY UPDATE XXX
FOR UPDATEXXXX

13.3.3. 页级锁 #

除表级锁和行级锁外,系统在共享缓冲池中还使用页级共享/排他锁来控制对表磁盘页面的读写访问。在抓取或更新元组后,这些锁会立即释放。应用开发者通常无需关注页级锁。

13.3.4. 死锁 #

当两个或多个事务彼此持有对方下一步操作所需的物理锁时,系统将陷入彼此无限等待的死锁状态。PostgreSQL 内置了死锁检测后台守护机制,一旦检测到死锁成环,系统会自动牺牲并回滚其中一个参与事务以打破死锁。

预防死锁的最佳工程实践是:确保所有业务应用程序在访问多个对象时,始终严格遵循统一、固定的物理先后顺序申请加锁。

13.3.5. 咨询锁 #

PostgreSQL 提供了具有应用自定义业务语义的全局分布式锁机制,被称为咨询锁(Advisory Locks)。系统不会强制执行其约束,完全由应用程序协同使用。咨询锁支持基于 64 位整数键或两个 32 位整数键加锁。

咨询锁支持两类生命周期模式:会话级(Session-level,直到显式调用释放函数或客户端连接断开时才释放)与事务级(Transaction-level,随当前事务的提交或回滚自动释放)。相关管理函数详见 Section 9.28.10。