2025年9月25日: PostgreSQL 18 发布!
支持的版本: 当前 (18) / 17 / 16 / 15 / 14 / 13
开发版本: devel
不支持的版本: 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

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 获取表级锁,并在必要时等待任何冲突的锁被释放。如果指定了 NOWAIT,则 LOCK 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 在事务块外部是无用的:锁只会保留到语句完成。因此,如果 LOCK 在事务块外部使用,PostgreSQL 会报告错误。使用 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 中的语法兼容。

提交更正

如果您在文档中发现任何不正确、与您对特定功能的体验不符或需要进一步说明的内容,请使用 此表单 报告文档问题。