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 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
的正确权限,或成为表的拥有者或超级用户。如果用户对表拥有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 节和锁定子句中的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 SHARE
、ACCESS EXCLUSIVE
和SHARE UPDATE EXCLUSIVE
锁模式之外,PostgreSQL锁模式和LOCK TABLE
语法与Oracle中的锁模式和语法兼容。