LOCK

Name

LOCK  --  明确地锁定一个表

Synopsis

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

这里 lockmode 可以是下列之一∶

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

输入

name

要锁定的现存表的名字(可以有模式修饰).

ACCESS SHARE MODE

注意: 这个锁模式对被查询的表自动生效。

这是最小限制的锁模式,只与 ACCESS EXCLUSIVE 模式冲突。 它用于保护被查询的表免于被并行的 ALTER TABLEDROP TABLEVACUUM FULL 对同一表操作的语句修改。

ROW SHARE MODE

注意: 任何 SELECT...FOR UPDATE 语句执行时自动生效。

与 EXCLUSIVE 和 ACCESS EXCLUSIVE 锁模式冲突。

ROW EXCLUSIVE MODE

注意: 任何 UPDATEDELETEINSERT 语句执行时自动生效。

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

SHARE UPDATE EXCLUSIVE MODE

Note: VACUUM (没有 FULL) 自动要求.

和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 TABLEVACUUM FULL 执行时自动生效。这是最严格的约束锁,它 保护一个被锁定的表不被任何其他并行的操作更改。

注意: 一个不合格的 LOCK TABLE 同样要求这个锁模式 (例如,一条没有显式锁模式选项的命令)。

与所有锁模式冲突.

输出

LOCK TABLE

成功获取锁之后的返回.

ERROR name: Table does not exist.

如果name 不存在,返回此信息.

描述

LOCK TABLE 控制一次事务的生命期内对某表的并行访问. PostgreSQL 在可能的情况下尽可能使用最小约束的锁模式。 LOCK TABLE 在你需要时提供更有约束力的锁。

RDBMS 锁定使用下面术语:

EXCLUSIVE

一个排它锁禁止其它同类型的锁获得批准.(注意∶ROW EXCLUSIVE 模式 并不完全遵循这个命名规则,因为它是在表一级共享的;它只是相对于 要更新的行而言是排它的.)

SHARE

共享锁允许其它(事务)也持有同类型锁,但是禁止对应的 EXCLUSIVE 锁获得批准.

ACCESS

锁定表结构.

ROW

锁定独立的行.

例如,假设一个应用在 READ COMMITED 隔离级别上运行事务, 并且它需要保证在表中的数据在事务的运行过程中都存在。要实现这个目的,你 可以在查询之前对表使用 SHARE 锁模式进行锁定。这样将保护数据不被 并行修改并且为任何更进一步的对表的读操作提供实际的当前状态的数据, 因为 SHARE 锁模式与任何写操作需要的 ROW EXCLUSIVE 模式冲突,并且你的 LOCK TABLE name IN SHARE MODE 语句将等到所有并行的写操作提交或回卷后才执行。 因此,一旦你获得该锁,那么就不会存在未提交的写操作.

注意: 当运行在 SERIALIZABLE 隔离级别并且你需要读取真实状态的数据时, 你必须在执行任何DML语句 之前运行一个 LOCK TABLE 语句。 一个可串行化事务的数据视图将在其第一个DML语句开始的时候冻结住. 稍后的 LOCK 将仍然阻止并发的写 --- 但它不能保证 事务读取的东西对应最近提交的数值。

除了上面的要求外,如果一个事务准备修改一个表中的数据, 那么应该使用 SHARE ROW EXCLUSIVE 锁模式以避免死锁情况(当两个 并行的事务试图以 SHARE 模式锁住表然后试图更改表中的数据时, 两个事务(隐含的)都需要 ROW EXCLUSIVE 锁模式,而此模式与并行的 SHARE 锁冲突)。

继续上面的死锁(两个事务彼此等待)问题, 你应该遵循两个通用的规则以避免死锁条件:

注意: PostgreSQL 的确检测死锁, 并将回卷至少一个等待的事务以解决死锁。

注意

LOCK ... IN ACCESS SHARE MODE 需要在目标表上有 SELECT 权限.所有其它形式的 LOCK 需要 UPDATE 和/或 DELETE 权限.

LOCK 只是在一个事务块的内部有用 (BEGIN...COMMIT),因为锁在事务结束的时候 马上被释放.出现在任意事务块外面的 LOCK 都自动生成 一个自包含的事务,因此该锁在获取之后马上被丢弃.

LOCK 只在事务内部使用.

用法

演示在往一个外键表上插入时在有主键的表上使用 SHARE 的锁:

BEGIN WORK;
LOCK TABLE films IN SHARE MODE;
SELECT id FROM films 
    WHERE name = 'Star Wars: Episode I - The Phantom Menace';
-- 如果记录没有返回则回卷
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) 里面的兼容。