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

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

LOCK

LOCK — 锁定表

大纲

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

where lockmode is one of:

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

描述

LOCK TABLE获取一个表级锁;如有必要,会等待任何冲突锁被释放。 如果指定了NOWAIT,LOCK TABLE就不会等待获取所需的锁: 如果无法立即获得,命令将被中止并报错。锁一旦获得,就会一直持有到当前事务结束。 (没有UNLOCK TABLE命令;锁总是在事务结束时释放。)

为引用表的命令自动获取锁时,PostgreSQL始终使用限制最少的可用锁模式。LOCK TABLE用于可能需要更严格锁定的情况。例如,假设一个应用在 Read Committed(读已提交)隔离级别运行事务,并且需要确保表中的数据在事务期间保持稳定。为此,可以在查询之前对表获取SHARE锁。这会阻止并发数据更改,确保后续对表的读取能看到已提交数据的稳定视图,因为SHARE锁模式与写入者获取的ROW EXCLUSIVE锁冲突,而你的LOCK TABLE name IN SHARE MODE语句会等待,直到所有并发持有ROW EXCLUSIVE模式锁的事务提交或回滚。因此,一旦获得该锁,就不存在尚未提交的写入;而且在释放该锁之前,也不会开始任何写入。

要在 Serializable(可串行化)隔离级别下运行事务时获得类似的效果,你必须先执行LOCK TABLE语句,然后才能执行任何SELECT或数据修改语句。一个可串行化事务的数据视图将在它的第一条SELECT或数据修改语句开始时被冻结。事务中较晚执行的LOCK TABLE仍然可以阻止并发写—但它无法确保该事务读取到的是最新已提交的值。

如果这类事务还要修改表中的数据,那么它应使用SHARE ROW EXCLUSIVE锁模式, 而不是SHARE模式。这样可以确保同一时间只有一个这类事务在运行。 否则就可能发生死锁:两个事务都可能先获得SHARE模式, 然后都无法再获得实际执行更新所需的ROW EXCLUSIVE模式。 (注意,事务自己的锁永远不会互相冲突,因此事务在持有SHARE模式时仍可获得 ROW EXCLUSIVE模式,但前提是没有其他人持有SHARE模式。) 为避免死锁,要确保所有事务都按相同顺序对相同对象获取锁;如果同一对象需要多种锁模式, 则事务应始终先获取限制最严格的模式。

关于锁模式和锁策略的更多信息,请参见第 12.3 节。

参数

name

要锁定的现有表的名称(可选模式限定)。如果在表名前指定了

命令LOCK TABLE a, b;等效于 LOCK TABLE a; LOCK TABLE b;。这些表会按 LOCK TABLE命令中指定的顺序逐个锁定。

lockmode

锁模式指定该锁会与哪些锁冲突。锁模式见第 12.3 节。

如果未指定锁模式,则使用限制最严格的ACCESS EXCLUSIVE模式。

NOWAIT

指定LOCK TABLE不等待任何冲突锁被释放: 如果指定的锁无法在不等待的情况下立即获得,事务就会中止。

注解

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

LOCK TABLE只在事务块(BEGIN/COMMIT对)内才有用, 因为锁会在事务一结束就被释放。出现在任何事务块之外的LOCK TABLE命令会构成一个独立的事务,因此锁在获得之后立刻就会被释放。

LOCK TABLE只处理表级锁,因此名称中带有ROW的模式其实都不准确。这些模式名称通常应理解为:用户打算在被锁定的表中获取行级锁。此外,ROW EXCLUSIVE模式本身也是一种可共享的表锁。请记住,就LOCK TABLE而言,所有锁模式的语义完全相同,差别只在于哪些模式彼此冲突。关于如何获取真正的行级锁,请参阅第 12.3.2 节以及FOR UPDATE 子句(位于SELECT参考文档中)。

示例

在准备向外键表执行插入时,在主键表上获取一个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;

兼容性

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

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

提交更正

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