pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
LOCK — 在事务内显式锁定一个表
LOCK [ TABLE ]nameLOCK [ TABLE ]nameIN [ ROW | ACCESS ] { SHARE | EXCLUSIVE } MODE LOCK [ TABLE ]nameIN SHARE ROW EXCLUSIVE MODE
name要锁定的现有表的名称。
这种锁模式会在被查询的表上自动获取。
这是限制性最低的锁模式。它只与 ACCESS EXCLUSIVE 模式冲突。它用于保护表不被并发的 ALTER TABLE、 DROP TABLE 和 VACUUM 命令修改。
由 SELECT...FOR UPDATE 自动获取。它是共享锁,但之后可以升级为 ROW EXCLUSIVE 锁。
与 EXCLUSIVE 和 ACCESS EXCLUSIVE 锁模式冲突。
由 UPDATE、 DELETE 和 INSERT 语句自动获取。
与 SHARE、SHARE ROW EXCLUSIVE、EXCLUSIVE 和 ACCESS EXCLUSIVE 模式冲突。
由 CREATE INDEX 自动获取。对整张表加共享锁。
与 ROW EXCLUSIVE、SHARE ROW EXCLUSIVE、EXCLUSIVE 和 ACCESS EXCLUSIVE 模式冲突。此模式保护表不被并发更新影响。
这与 EXCLUSIVE MODE 类似,但允许别人持有 SHARE ROW 锁。
与 ROW EXCLUSIVE、SHARE、SHARE ROW EXCLUSIVE、 EXCLUSIVE 和 ACCESS EXCLUSIVE 模式冲突。
此模式比 SHARE ROW EXCLUSIVE 限制性更强。它阻塞所有并发的 ROW SHARE/SELECT...FOR UPDATE 查询。
与 ROW SHARE、ROW EXCLUSIVE、SHARE、SHARE ROW EXCLUSIVE、 EXCLUSIVE 和 ACCESS EXCLUSIVE 模式冲突。
由 ALTER TABLE、 DROP TABLE、VACUUM 语句自动获取。这是限制性最高的锁模式,与所有其他锁模式冲突,保护被锁表免受任何并发操作。
不带限定的 LOCK TABLE(即没有显式锁模式选项的命令)也会获取这种锁模式。
LOCK TABLE锁应用成功。
ERROR name: Table does not exist.如果 name 不存在则返回此消息。
LOCK TABLE 在事务期间控制对一个表的并发访问。 Postgres 在可能时总是使用限制性最低的锁模式。LOCK TABLE 用于你可能需要更严格锁定的场合。
RDBMS 锁定使用下列术语:
排他锁,阻止授予其他锁。
允许别人共享锁定。阻止 EXCLUSIVE 锁。
锁定表模式。
锁定单个行。
如果未指定 EXCLUSIVE 或 SHARE,则假定为 EXCLUSIVE。锁在事务期间存在。
例如,一个应用以 READ COMMITTED 隔离级别运行事务,并且需要确保表中的数据在事务期间保持存在。为此,你可以在查询之前对该表使用 SHARE 锁模式。这将保护数据不被并发更改,并为随后对该表的读取操作提供处于实际当前状态的数据,因为 SHARE 锁模式与写者取得的任何 ROW EXCLUSIVE 锁冲突,而你的 LOCK TABLE 语句会等待任何并发写操作提交或回滚。name IN SHARE MODE
要在以 SERIALIZABLE 隔离级别运行事务时读取处于真实当前状态的数据,你必须在执行任何 DML 语句之前执行一条 LOCK TABLE 语句,因为正是在那时事务确定哪些并发更改对自己可见。
除上述要求外,如果事务要更改表中的数据,就应取得 SHARE ROW EXCLUSIVE 锁模式,以防止两个并发事务都试图以 SHARE 模式锁定该表、然后再试图更改表中数据时出现死锁——两者(隐式)取得的 ROW EXCLUSIVE 锁模式都与并发的 SHARE 锁冲突。
继续讨论上面提出的死锁(两个事务互相等待)问题:你应当遵循两条通用规则来防止死锁条件:
事务必须以相同的顺序对相同的对象获取锁。
例如,如果一个应用先更新行 R1 再更新行 R2(在同一个事务中),那么第二个应用如果稍后要更新行 R1(在单个事务中),就不应先更新行 R2。相反,它应按照与第一个应用相同的顺序更新行 R1 和 R2。
只有两个冲突锁模式之一是自冲突的(即同一时刻只能被一个事务持有)时,事务才应同时获取这两个锁模式。如果涉及多种锁模式,事务应总是先获取限制性最高的模式。
前面在讨论使用 SHARE ROW EXCLUSIVE 模式而非 SHARE 模式时已给出过这条规则的一个例子。
Postgres 确实会检测死锁,并会回滚至少一个等待中的事务来解决死锁。
LOCK 是一种 Postgres 语言扩展。
除 ACCESS SHARE/EXCLUSIVE 锁模式外,其他所有 Postgres 锁模式和 LOCK TABLE 语法都与 Oracle 中的对应语法兼容。
LOCK 只在事务内部起作用。
演示在准备向外键表执行插入时,在主键表上获取一个 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;
SQL92 中没有 LOCK TABLE,而是使用 SET TRANSACTION 来指定事务的并发级别。我们也支持这一点;详见 SET 。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。