## 锁 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 ``` ## 描述 `锁表`获得表级锁,如有必要,等待释放任何冲突的锁。如果`现在等待`被指定,`锁表`不等待获取所需的锁:如果不能立即获取,则中止命令并发出错误。一旦获得,该锁将在当前事务的剩余部分中保持。(没有`解锁表`命令;锁总是在事务结束时释放。) 当视图被锁定时,视图定义查询中出现的所有关系也以相同的锁定模式递归锁定。 当为引用表的命令自动获取锁时,PostgreSQL 总是使用限制最少的锁模式。`锁表`提供了您可能需要更多限制性锁定的情况。例如,假设应用程序在`阅读已提交`隔离级别,需要确保表中的数据在事务期间保持稳定。为此,您可以获得`分享`在查询之前对表进行锁定模式。这将防止并发数据更改并确保对表的后续读取看到已提交数据的稳定视图,因为`分享`锁定模式与`排独家`作家获得的锁,以及您的`锁定表 *`姓名`* 在分享模式`声明将等到任何并发持有人`排独家`模式锁定提交或回滚。因此,一旦您获得锁,就没有未提交的未提交写入;此外,在您释放锁之前,没有人可以开始。 在运行事务时达到类似的效果`可重复阅读`或者`可序列化`隔离级别,你必须执行`锁表`执行任何之前的语句`选择`或数据修改声明。一种`可重复阅读`或者`可序列化`事务的数据视图将在第一次被冻结`选择`或数据修改语句开始。一种`锁表`在事务的后期仍然会阻止并发写入——但它不能确保事务读取的内容与最新提交的值相对应。 如果此类事务要更改表中的数据,则应使用`共享行独家`锁定模式而不是`分享`模式。这可确保一次仅运行一个此类事务。没有这个,死锁是可能的:两个事务可能都获得`分享`模式,然后也无法获取`排独家`模式来实际执行他们的更新。(注意事务自己的锁永远不会冲突,所以事务可以获取`排独家`持有时的模式`分享`模式——但如果其他人持有则不会`分享`模式。)为避免死锁,请确保所有事务以相同的顺序获取相同对象的锁,如果单个对象涉及多种锁模式,则事务应始终首先获取最严格的模式。 有关锁定模式和锁定策略的更多信息,请参见[第 13.3 节](explicit-locking.html). ## 参数 *`姓名`* 要锁定的现有表的名称(可选模式限定)。如果`只要`在表名之前指定,只有该表被锁定。如果`只要`未指定时,该表及其所有后代表(如果有)将被锁定。可选地,`*`可以在表名之后指定以明确指示包含后代表。 命令`锁定表 a,b;`相当于`锁定表a;锁定表 b;`.这些表按照指定的顺序一一锁定`锁表`命令。 *`锁定模式`* 锁定模式指定此锁定与哪些锁定冲突。锁定模式在[第 13.3 节](explicit-locking.html). 如果未指定锁定模式,则`访问独家`,最严格的模式,被使用。 `现在等待` 指定`锁表`不应该等待任何有冲突的锁被释放:如果不等待就不能立即获取指定的锁,则事务被中止。 ## 笔记 `锁定表...在访问共享模式`需要`选择`目标表的权限。`锁定表...在排他模式`需要`插入`,`更新`,`删除`, 要么`截短`目标表的权限。所有其他形式的`锁`需要表级`更新`,`删除`, 要么`截短`特权。 对视图执行锁定的用户必须对视图具有相应的权限。此外,视图的所有者必须对底层基础关系具有相关权限,但执行锁定的用户不需要底层基础关系的任何权限。 `锁表`在事务块之外是无用的:锁只会保持到语句完成。因此 PostgreSQL 报告一个错误如果`锁`在事务块之外使用。采用[`开始`](sql-begin.html)和[`犯罪`](sql-commit.html)(要么[`回滚`](sql-rollback.html)) 来定义一个事务块。 `锁表`只处理表级锁,因此涉及的模式名称`排`都是用词不当。这些模式名称通常应该被解读为表明用户在锁定表中获取行级锁的意图。还,`排独家`mode 是一个可共享的表锁。请记住,所有锁定模式都具有相同的语义`锁表`是有关的,仅在关于哪些模式与哪些模式冲突的规则上有所不同。有关如何获取实际行级锁的信息,请参阅[第 13.3.2 节](explicit-locking.html#LOCKING-ROWS)和[锁定条款](sql-select.html#SQL-FOR-UPDATE-SHARE)在里面[选择](sql-select.html)文档。 ## 例子 获得一个`分享`执行插入外键表时锁定主键表: ``` 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; ``` 拿一个`共享行独家`执行删除操作时锁定主键表: ``` 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 标准中,它改为使用`设置交易`指定事务的并发级别。PostgreSQL 也支持。看[设置交易](sql-set-transaction.html)详情。 除了`访问共享`,`访问独家`, 和`共享更新独家`锁定模式、PostgreSQL 锁定模式和`锁表`语法与 Oracle 中的语法兼容。