支持的版本:当前 (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语句。当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在事务块之外是无用的:锁只会保持到语句完成。因此,如果在事务块之外使用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 中的相同。

提交更正

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