pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
LOCK — 锁定一个表
LOCK [ TABLE ]name[, ...] [ INlockmodeMODE ] wherelockmodeis one of: ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE | SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE
LOCK TABLE 获取一个表级锁,必要时会等待任何冲突的锁被释放。一旦取得,该锁会保持到当前事务结束。(没有 UNLOCK TABLE 命令;锁总是在事务结束时释放。)
在为引用表的命令自动获取锁时, PostgreSQL 总是使用限制性最低的锁模式。LOCK TABLE 用于你可能需要更严格锁定的场合。例如,假设一个应用以读已提交隔离级别运行事务,并且需要确保表中的数据在事务期间保持稳定。为此,你可以在查询之前对该表取得 SHARE 锁模式。这将阻止并发数据更改,并确保随后对该表的读取看到已提交数据的稳定视图,因为 SHARE 锁模式与写者取得的 ROW EXCLUSIVE 锁冲突,而你的 LOCK TABLE 语句会等待任何并发持有 name IN SHARE MODEROW EXCLUSIVE 模式锁的事务提交或回滚。因此,一旦你取得了锁,就不存在未提交的写;而且在释放锁之前也不会有新的写开始。
要在以可串行化隔离级别运行事务时达到类似效果,你必须在执行任何数据修改语句之前执行 LOCK TABLE 语句。可串行化事务的数据视图会在其第一条数据修改语句开始时冻结。之后再执行 LOCK TABLE 仍能阻止并发写——但它无法确保事务读取到的内容对应于最新提交的值。
如果这类事务要更改表中的数据,就应使用 SHARE ROW EXCLUSIVE 锁模式而不是 SHARE 模式。这确保同一时刻只有一个这类事务在运行。否则可能出现死锁:两个事务可能都取得了 SHARE 模式,然后又都无法再取得 ROW EXCLUSIVE 模式来实际执行更新。(注意,事务自身的锁永不冲突,因此持有 SHARE 模式的事务可以再取得 ROW EXCLUSIVE 模式——但如果别人持有 SHARE 模式则不行。)为避免死锁,应确保所有事务以相同的顺序对相同的对象获取锁,而且如果单个对象涉及多种锁模式,事务应总是先获取限制性最高的模式。
关于锁模式和锁策略的更多信息,请参见第 12.3 节。
name要锁定的现有表的名称(可选模式限定)。
命令 LOCK a, b; 等价于 LOCK a; LOCK b;。各表按 LOCK 命令中指定的顺序逐一锁定。
lockmode锁模式指定该锁会与哪些锁冲突。锁模式见第 12.3 节。
如果未指定锁模式,则使用限制最严格的ACCESS EXCLUSIVE模式。
LOCK ... IN ACCESS SHARE MODE 要求在目标表上具有 SELECT 权限。LOCK 的所有其他形式都要求 UPDATE 和/或 DELETE 权限。
LOCK 只在事务块(BEGIN/COMMIT 对)内部有用,因为锁在事务一结束就被丢弃。出现在任何事务块之外的 LOCK 命令构成一个自包含的事务,因此锁一取得就会被丢弃。
LOCK TABLE 只处理表级锁,因此涉及 ROW 的模式名都是名不副实的。这些模式名一般应理解为表明用户意图在被锁表内获取行级锁。此外, ROW EXCLUSIVE 模式是一种可共享的表锁。请记住,就 LOCK TABLE 而言,所有锁模式的语义都相同,只在哪些模式与哪些模式冲突的规则上有差别。
在准备向外键表执行插入时,在主键表上获取一个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中的对应语法兼容。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。