2024年9月26日:PostgreSQL 17 发布!
支持的版本:当前 (17) / 16 / 15 / 14 / 13 / 12
开发版本:devel
不受支持的版本: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 语句。 REPEATABLE READSERIALIZABLE 事务的数据视图将在其第一个 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 中存在的锁定模式和语法兼容。

提交更正

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