Redrock Postgres 搜索 英文
版本: 9.3 / 9.4 / 9.5 / 9.6 / 10 / 11 / 12 / 13 / 14 / 15 / 16 / 17

LOCK

LOCK — 锁定表

概要

LOCK [ TABLE ] [ ONLY ] 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 获取表级锁定,在需要时等待释放任何冲突的锁定。如果指定了 NOWAITLOCK TABLE 不会等待获取所需的锁定:如果不能立即获取,这个命令将中止并发出错误。一旦获取了锁定,它将在当前事务的剩余时间内被保持。(没有 UNLOCK TABLE 命令;锁定总是会在事务结束时释放。)

锁定视图时,视图定义查询中出现的任何关联模式也会以同一种锁定模式循环锁定。

在自动为引用表中的命令获取锁定时,PostgreSQL 总是尽可能使用最不严格的锁定模式。LOCK TABLE 提供了可能需要较严格锁定情况下的解决方案。例如,假设某个应用程序在 READ COMMITTED 隔离级别下运行事务,需要确保表中的数据在事务持续期内保持稳定。为此,您可以在查询之前获取表上的 SHARE 锁定模式。这将防止并发数据变更,并确保对表的后续读取可见提交数据的稳定视图,因为 SHARE 锁定模式与写操作获取的 ROW EXCLUSIVE 锁定冲突,并且 LOCK TABLE name IN SHARE MODE 语句将等待在 ROW EXCLUSIVE 模式锁定下发生的并发持有者提交或回滚。因此,一旦获取锁定之后,将不会出现未提交的待解决写入;并且,在您释放锁定之前也无法开始任何写入。

REPEATABLE READSERIALIZABLE 隔离级别下运行事务时,为了达到类似效果,您必须在执行任何 SELECT 或数据修改语句之前执行 LOCK TABLE 语句。在事务的第一个 SELECT 或数据修改语句开始时,将冻结事务对数据的视图。后期事务中的 LOCK TABLE 仍然可以防止并发写入,但无法确保事务读取的是最新提交值。

如果该类型的事务要变更表中的数据,那么它应该使用 SHARE ROW EXCLUSIVE 锁定模式,而不是 SHARE 模式。它可以确保一次只运行这种类型的单一事务。否则,可能出现死锁:两个事务可能会都获得 SHARE 模式,然后无法再获得 ROW EXCLUSIVE 模式来执行更新(请注意,事务自身锁定不会产生冲突,因此当它拥有 SHARE 时可以获得 ROW EXCLUSIVE 模式,但其他任何人持有 SHARE 模式时就不行)。为了避免死锁,请确保所有事务以相同的顺序对相同对象进行锁定,并且如果单个对象涉及多种锁定模式,那么事务应始终首先获取最严格的模式。

有关锁模式和锁定策略的更多信息,请参见第 13.3 节

参数

name

要锁定的现有表的名称(可选地以模式限定)。如果在表名称之前指定了 ONLY,则仅锁定该表。如果未指定 ONLY,则会锁定该表及其所有子代表(如果存在)。也可以在表名称后面指定 *,以明确表示包含子代表。

命令 LOCK TABLE a, b; 等效于 LOCK TABLE a; LOCK TABLE b;。将按照在 LOCK TABLE 命令中指定的顺序来逐个锁定表。

lockmode

锁模式指定该锁与哪些锁冲突。在第 13.3 节中对锁模式进行了说明。

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

NOWAIT

指定 LOCK TABLE 不应等待任何冲突锁的释放:如果无法立即获取指定的锁而无需等待,则会中止事务。

注释

要锁定表,用户必须对指定的 lockmode 具有正确的权限。如果用户对表具有 MAINTAINUPDATEDELETETRUNCATE 权限,则允许任何 lockmode。如果用户对表具有 INSERT 权限,则允许 ROW EXCLUSIVE MODE(或如 第 13.3 节 中说明的冲突程度较低的模式)。如果用户对表具有 SELECT 权限,则允许 ACCESS SHARE MODE

对视图执行锁定的用户必须具有对该视图的相应权限。此外,在默认情况下,视图的所有者必须对基础基本关系拥有相关权限,而对视图执行锁定的用户不需要对基础基本关系有任何权限。但是,如果视图将 security_invoker 设置为 true(请参见 CREATE VIEW),则对视图执行锁定的用户(而非视图所有者)必须对基础基本关系拥有相关权限。

在事务块外,LOCK TABLE 无用:锁只保持到该语句结束。因此,如果在事务块外使用了 LOCKPostgreSQL 会报告一个错误。使用 BEGINCOMMIT(或 ROLLBACK)来定义事务块。

LOCK TABLE 仅处理表级锁,因此涉及 ROW 的模式名称都是错误的。这些模式名称通常应被视为表示用户在锁定表中获取行级锁的意图。此外,ROW EXCLUSIVE 模式是一个可共享表锁。请记住,就 LOCK TABLE 而言,所有锁模式具有相同的语义,仅在有关哪些模式与哪些模式冲突的规则方面有所不同。有关如何获取实际行级锁的信息,请参阅 第 13.3.2 节锁定子句中的 SELECT 文档。

示例

在即将向外键表中执行插入时,针对主键表获取 SHARE

BEGIN WORK;
LOCK TABLE films IN SHARE MODE;
SELECT id FROM films
    WHERE name = 'Star Wars: Episode I - The Phantom Menace';
-- Do ROLLBACK if record was not returned
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 SHAREACCESS EXCLUSIVESHARE UPDATE EXCLUSIVE 锁模式以外,PostgreSQL 锁模式和 LOCK TABLE 语法与 Oracle 中存在的锁模式和语法兼容。