↑↓ 选择 ↵ 打开 ⌫ 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1 / 7.0 / 6.5 / 6.4
历史版本PostgreSQL 7.3 已于 2007 年 11 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本。

LOCK

LOCK — 显式锁定一个表

大纲

LOCK [ TABLE ] name [, ...]
LOCK [ TABLE ] name [, ...] IN lockmode MODE

where lockmode is one of:

        ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE |
        SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE
  

输入

name

要锁定的现有表的名称(可选模式限定)。

ACCESS SHARE MODE

这是限制性最低的锁模式。它只与 ACCESS EXCLUSIVE 模式冲突。它用于保护表不被并发的 ALTER TABLE、 DROP TABLE 和 VACUUM FULL 命令修改。

注意

SELECT 命令会在被引用的表上获取这种模式的锁。一般而言,任何只读表而不修改表的查询都会获取这种锁模式。

ROW SHARE MODE

与 EXCLUSIVE 和 ACCESS EXCLUSIVE 锁模式冲突。

注意

SELECT FOR UPDATE 命令会在目标表上获取这种模式的锁(此外还会在其他被引用但未被 FOR UPDATE 选取的表上获取 ACCESS SHARE 锁)。

ROW EXCLUSIVE MODE

与 SHARE、SHARE ROW EXCLUSIVE、EXCLUSIVE 和 ACCESS EXCLUSIVE 模式冲突。

注意

UPDATE、 DELETE 和 INSERT 命令会在目标表上获取这种锁模式(此外还会在其他被引用的表上获取 ACCESS SHARE 锁)。一般而言,任何修改表中数据的查询都会获取这种锁模式。

SHARE UPDATE EXCLUSIVE MODE

与 SHARE UPDATE EXCLUSIVE、SHARE、SHARE ROW EXCLUSIVE、 EXCLUSIVE 和 ACCESS EXCLUSIVE 模式冲突。此模式保护表不被并发的模式更改和 VACUUM 运行影响。

注意

由(不带 FULL 的) VACUUM 获取。

SHARE MODE

与 ROW EXCLUSIVE、SHARE UPDATE EXCLUSIVE、 SHARE ROW EXCLUSIVE、EXCLUSIVE 和 ACCESS EXCLUSIVE 模式冲突。此模式保护表不被并发数据更改影响。

注意

由 CREATE INDEX 获取。

SHARE ROW EXCLUSIVE MODE

与 ROW EXCLUSIVE、SHARE UPDATE EXCLUSIVE、SHARE、 SHARE ROW EXCLUSIVE、EXCLUSIVE 和 ACCESS EXCLUSIVE 模式冲突。

注意

任何 PostgreSQL 命令都不会自动获取这种锁模式。

EXCLUSIVE MODE

与 ROW SHARE、ROW EXCLUSIVE、SHARE UPDATE EXCLUSIVE、 SHARE、SHARE ROW EXCLUSIVE、 EXCLUSIVE 和 ACCESS EXCLUSIVE 模式冲突。此模式只允许并发的 ACCESS SHARE,也就是说,只有对该表的读取才能与持有此锁模式的事务并行进行。

注意

任何 PostgreSQL 命令都不会自动获取这种锁模式。

ACCESS EXCLUSIVE MODE

与所有锁模式冲突。此模式保证持有者是唯一以任何方式访问该表的事务。

注意

由 ALTER TABLE、 DROP TABLE 和 VACUUM FULL 语句获取。它也是未显式指定模式的 LOCK TABLE 语句的默认锁模式。

输出

LOCK TABLE

锁获取成功。

ERROR name: Table does not exist.

如果 name 不存在则返回此消息。

描述

LOCK TABLE 获取一个表级锁,必要时会等待任何冲突的锁被释放。一旦取得,该锁会保持到当前事务结束。(没有 UNLOCK TABLE 命令;锁总是在事务结束时释放。)

在为引用表的命令自动获取锁时, PostgreSQL 总是使用限制性最低的锁模式。LOCK TABLE 用于你可能需要更严格锁定的场合。

例如,假设一个应用以 READ COMMITTED 隔离级别运行事务,并且需要确保表中的数据在事务期间保持稳定。为此,你可以在查询之前对该表取得 SHARE 锁模式。这将阻止并发数据更改,并确保随后对该表的读取看到已提交数据的稳定视图,因为 SHARE 锁模式与写者取得的 ROW EXCLUSIVE 锁冲突,而你的 LOCK TABLE name IN SHARE MODE 语句会等待任何并发持有 ROW EXCLUSIVE 模式锁的事务提交或回滚。因此,一旦你取得了锁,就不存在未提交的写;而且在释放锁之前也不会有新的写开始。

注意

要在以 SERIALIZABLE 隔离级别运行事务时达到类似效果,你必须在执行任何 DML 语句之前执行 LOCK TABLE 语句。可串行化事务的数据视图会在其第一条 DML 语句开始时冻结。之后再执行 LOCK 仍能阻止并发写——但它无法确保事务读取到的内容对应于最新提交的值。

如果这类事务要更改表中的数据,就应使用 SHARE ROW EXCLUSIVE 锁模式而不是 SHARE 模式。这确保同一时刻只有一个这类事务在运行。否则可能出现死锁:两个事务可能都取得了 SHARE 模式,然后又都无法再取得 ROW EXCLUSIVE 模式来实际执行更新。(注意,事务自身的锁永不冲突,因此持有 SHARE 模式的事务可以再取得 ROW EXCLUSIVE 模式——但如果别人持有 SHARE 模式则不行。)

为防止死锁条件,可以遵循两条通用规则:

  • 事务必须以相同的顺序对相同的对象获取锁。

    例如,如果一个应用先更新行 R1 再更新行 R2(在同一个事务中),那么第二个应用如果稍后要更新行 R1(在单个事务中),就不应先更新行 R2。相反,它应按照与第一个应用相同的顺序更新行 R1 和 R2。

  • 如果单个对象涉及多种锁模式,事务应总是先获取限制性最高的模式。

    前面在讨论使用 SHARE ROW EXCLUSIVE 模式而非 SHARE 模式时已给出过这条规则的一个例子。

PostgreSQL 确实会检测死锁,并会回滚至少一个等待中的事务来解决死锁。如果让应用严格遵循上述规则不现实,另一个解决办法是准备好在事务被死锁中止时重试它们。

锁定多个表时,命令 LOCK a, b; 等价于 LOCK a; LOCK b;。各表按 LOCK 命令中指定的顺序逐一锁定。

注意

LOCK ... IN ACCESS SHARE MODE 要求在目标表上具有 SELECT 权限。LOCK 的所有其他形式都要求 UPDATE 和/或 DELETE 权限。

LOCK 只在事务块(BEGIN...COMMIT)内部有用,因为锁在事务一结束就被丢弃。出现在任何事务块之外的 LOCK 命令构成一个自包含的事务,因此锁一取得就会被丢弃。

RDBMS 锁定使用下列标准术语:

EXCLUSIVE

排他锁阻止授予其他同类型的锁。

SHARE

共享锁允许别人也持有同类型的锁,但阻止授予相应的 EXCLUSIVE 锁。

ACCESS

锁定表模式。

ROW

锁定单个行。

PostgreSQL 并未完全遵循这套术语。LOCK TABLE 只处理表级锁,因此涉及 ROW 的模式名都是名不副实的。这些模式名一般应理解为表明用户意图在被锁表内获取行级锁。此外, ROW EXCLUSIVE 模式也没有准确遵循这一命名约定,因为它是一种可共享的表锁。请记住,就 LOCK TABLE 而言,所有锁模式的语义都相同,只在哪些模式与哪些模式冲突的规则上有差别。

用法

在准备向外键表执行插入时,在主键表上获取一个 SHARE 锁:

BEGIN WORK;
LOCK TABLE films IN SHARE MODE;
SELECT id FROM films
    WHERE name = 'Star Wars: Episode I - The Phantom Menace';
-- 如果未返回记录则执行 ROLLBACK
INSERT INTO films_user_comments VALUES
    (_id_, 'GREAT! I was waiting for it for so long!');
COMMIT WORK;
   

在准备执行删除操作时,在主键表上获取一个 SHARE ROW EXCLUSIVE 锁:

BEGIN WORK;
LOCK TABLE films IN SHARE ROW EXCLUSIVE MODE;
DELETE FROM films_user_comments WHERE id IN
    (SELECT id FROM films WHERE rating < 5);
DELETE FROM films WHERE rating < 5;
COMMIT WORK;
   

兼容性

SQL92

SQL92 中没有 LOCK TABLE,而是使用 SET TRANSACTION 来指定事务的并发级别。我们也支持这一点;详见 SET TRANSACTION。

除 ACCESS SHARE、ACCESS EXCLUSIVE 和 SHARE UPDATE EXCLUSIVE 锁模式外, PostgreSQL 的锁模式和 LOCK TABLE 语法与 Oracle(TM) 中的对应语法兼容。

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。