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

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.2 已于 2007 年 2 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本。

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
  

Inputs

name

要锁定的现有表的名称。

ACCESS SHARE MODE

注意

这种锁模式会在被查询的表上自动获取。

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

ROW SHARE MODE

注意

由 SELECT ... FOR UPDATE 自动获取。

与 EXCLUSIVE 和 ACCESS EXCLUSIVE 锁模式冲突。

ROW EXCLUSIVE MODE

注意

由 UPDATE、 DELETE 和 INSERT 语句自动获取。

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

SHARE UPDATE EXCLUSIVE MODE

注意

由(不带 FULL 的) VACUUM 自动获取。

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

SHARE MODE

注意

由 CREATE INDEX 自动获取。对整张表加共享锁。

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

SHARE ROW EXCLUSIVE MODE

注意

这与 EXCLUSIVE MODE 类似,但允许别人持有 ROW SHARE 锁。

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

EXCLUSIVE MODE

注意

此模式比 SHARE ROW EXCLUSIVE 限制性更强。它阻塞所有并发的 ROW SHARE/SELECT...FOR UPDATE 查询。

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

ACCESS EXCLUSIVE MODE

注意

由 ALTER TABLE、 DROP TABLE、VACUUM FULL 语句自动获取。这是限制性最高的锁模式,保护被锁表免受任何并发操作。

注意

不带限定的 LOCK TABLE(即没有显式锁模式选项的命令)也会获取这种锁模式。

与所有锁模式冲突。

Outputs

LOCK TABLE

锁获取成功。

ERROR name: Table does not exist.

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

描述

LOCK TABLE 在事务期间控制对一个表的并发访问。 PostgreSQL 在可能时总是使用限制性最低的锁模式。LOCK TABLE 用于你可能需要更严格锁定的场合。

RDBMS 锁定使用下列术语:

EXCLUSIVE

排他锁阻止授予其他同类型的锁。(注意:ROW EXCLUSIVE 模式没有完全遵循这一命名约定,因为它在表级别是共享的;只对正在被更新的特定行是排他的。)

SHARE

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

ACCESS

锁定表模式。

ROW

锁定单个行。

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

注意

要在以 SERIALIZABLE 隔离级别运行事务时读取处于实际当前状态的数据,你必须在执行任何 DML 语句之前执行 LOCK TABLE 语句。可串行化事务的数据视图会在其第一条 DML 语句开始时冻结。

除上述要求外,如果事务要更改表中的数据,就应取得 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 命令构成一个自包含的事务,因此锁一取得就会被丢弃。

用法

演示在准备向外键表执行插入时,在主键表上获取一个 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 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。