SQL COMMAND · 查询与数据操作
LOCK
锁定表
LOCK查询与数据操作引入 10(基线)现存至 20 devel0 次语法变更
- 动词
LOCK- 对象
—- 分组
- 查询与数据操作
- 引入版本
- 10(基线)
- 状态
- 现存
- 语法变更次数
- 0
- 手册小节数
- 5
版本轨迹
相对 PostgreSQL 17 无变化。
语法铁道图 PostgreSQL 18
沿轨道从左向右阅读,分岔表示选择,绕行表示可选,回环表示重复。方框为参数,点击带下划线的参数可展开子规则。
lockmode
锁模式 PostgreSQL 18
具体锁模式取决于操作变体、目标对象和执行阶段;同一命令可同时取得表锁与行锁。查看完整冲突矩阵
ACCESS SHARE· 表级锁LOCK TABLE … IN ACCESS SHARE MODE:显式请求此表级模式;省略 IN … MODE 时默认为 ACCESS EXCLUSIVE。ROW SHARE· 表级锁LOCK TABLE … IN ROW SHARE MODE:显式请求此表级模式;省略 IN … MODE 时默认为 ACCESS EXCLUSIVE。ROW EXCLUSIVE· 表级锁LOCK TABLE … IN ROW EXCLUSIVE MODE:显式请求此表级模式;省略 IN … MODE 时默认为 ACCESS EXCLUSIVE。SHARE UPDATE EXCLUSIVE· 表级锁LOCK TABLE … IN SHARE UPDATE EXCLUSIVE MODE:显式请求此表级模式;省略 IN … MODE 时默认为 ACCESS EXCLUSIVE。SHARE· 表级锁LOCK TABLE … IN SHARE MODE:显式请求此表级模式;省略 IN … MODE 时默认为 ACCESS EXCLUSIVE。SHARE ROW EXCLUSIVE· 表级锁LOCK TABLE … IN SHARE ROW EXCLUSIVE MODE:显式请求此表级模式;省略 IN … MODE 时默认为 ACCESS EXCLUSIVE。EXCLUSIVE· 表级锁LOCK TABLE … IN EXCLUSIVE MODE:显式请求此表级模式;省略 IN … MODE 时默认为 ACCESS EXCLUSIVE。ACCESS EXCLUSIVE· 表级锁LOCK TABLE … IN ACCESS EXCLUSIVE MODE:显式请求此表级模式;省略 IN … MODE 时默认为 ACCESS EXCLUSIVE。
语法概要
LOCK [ TABLE ] [ ONLY ]name[ * ] [, ...] [ INlockmodeMODE ] [ NOWAIT ] 其中lockmode可以是以下之一: 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 MODEROW EXCLUSIVE模式锁的事务提交或回滚。因此,一旦获得该锁,就不存在尚未提交的写入;而且在释放该锁之前,也不会有新的写入开始。
若要在REPEATABLE READ或SERIALIZABLE 隔离级别的事务中达到类似效果,你必须在执行任何SELECT 或数据修改语句之前执行LOCK TABLE语句。REPEATABLE READ或SERIALIZABLE事务的数据视图,会在其第一条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对应的权限。如果用户在该表上拥有MAINTAIN、UPDATE、DELETE或TRUNCATE权限,则允许使用任意 lockmode。如果用户在该表上拥有INSERT权限,则允许使用ROW EXCLUSIVE MODE(或冲突更少的锁模式,见第 13.3 节)。如果用户在该表上拥有SELECT权限,则允许使用ACCESS SHARE MODE。
在视图上执行锁定操作的用户必须对该视图拥有相应权限。此外,默认情况下,视图所有者必须对底层基关系拥有相关权限,而执行锁定操作的用户不需要对底层基关系拥有任何权限。但是,如果视图的security_invoker设置为true(参见CREATE VIEW),那么必须由执行锁定操作的用户而不是视图所有者,对底层基关系拥有相关权限。
LOCK TABLE在事务块外毫无用处:锁只会一直持有到该语句结束。因此,如果在事务块外使用LOCK,PostgreSQL会报告错误。请使用BEGIN和 COMMIT(或ROLLBACK)来定义事务块。
LOCK TABLE只处理表级锁,因此名称中带有ROW的模式其实都不准确。这些模式名称通常应理解为:用户打算在被锁定的表中获取行级锁。此外,ROW EXCLUSIVE模式本身也是一种可共享的表锁。请记住,就LOCK TABLE而言,所有锁模式的语义完全相同,差别只在于哪些模式彼此冲突。关于如何获取真正的行级锁,请参阅第 13.3.2 节和The Locking Clause(后者位于SELECT文档中)。
示例
在准备向外键表执行插入时,在主键表上获取一个SHARE锁:
BEGIN WORK;
LOCK TABLE films IN SHARE MODE;
SELECT id FROM films
WHERE name = 'Star Wars: Episode I - The Phantom Menace';
-- 如果未返回记录则执行 ROLLBACK
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 SHARE、ACCESS EXCLUSIVE和 SHARE UPDATE EXCLUSIVE锁模式外,PostgreSQL的锁模式和LOCK TABLE语法与Oracle中的对应语法兼容。
语法演化
相邻大版本之间的差异,新的在前。版本号链接到对应快照。
PostgreSQL 17← 16正文更新
正文更新PostgreSQL 16← 15正文更新
正文更新PostgreSQL 15← 14正文更新
正文更新PostgreSQL 14← 13正文更新
正文更新PostgreSQL 13← 12正文更新
正文更新PostgreSQL 11← 10正文更新
正文更新
同组命令
| 命令 | 动词 | 对象 | 版本变动 | 最近变更 |
|---|---|---|---|---|
COPY | COPY | — | 196 次 | |
| 在文件和表之间复制数据 | 现存 | |||
DELETE | DELETE | — | 182 次 | |
| 删除表中的行 | 现存 | |||
EXPLAIN | EXPLAIN | — | 195 次 | |
| 显示一个语句的执行计划 | 现存 | |||
INSERT | INSERT | — | 193 次 | |
| 在表中插入新行 | 现存 | |||
LOCK | LOCK | — | — | |
| 锁定表 | 现存 | |||
MERGE | MERGE | — | 182 次 | |
| 有条件地插入、更新或删除表中的行 | 现存 | |||
SELECT | SELECT | — | 176 次 | |
| 从表或视图中检索行 | 现存 | |||
UPDATE | UPDATE | — | 182 次 | |
| 更新表中的行 | 现存 | |||
VALUES | VALUES | — | — | |
| 计算一组行 | 现存 | |||
SELECT INTO | SELECT | INTO | 192 次 | |
| 根据查询结果定义一个新表 | 现存 | |||