LOCK [ TABLE ] name LOCK [ TABLE ] name IN [ ROW | ACCESS ] { SHARE | EXCLUSIVE } MODE LOCK [ TABLE ] name IN SHARE ROW EXCLUSIVE MODE
注意:这个锁模式对被查询的表自动生效。
注意:任何 SELECT FOR UPDATE 语句执行时自动生效。因为它是一个共享锁,以后可能更新为 ROW EXCLUSIVE 锁。
注意:任何 UPDATE, DELETE, INSERT 语句执行时自动生效。
注意:任何 CREATE INDEX 语句执行时自动附加。与 ROW EXCLUSIVE,SHARE ROW EXCLUSIVE,EXCLUSIVE 和 ACCESS EXCLUSIVE 模式冲突。这个模式防止一个表被并行更新。
注意:这个模式类似 EXCLUSIVE MODE,但是允许其他事务的 SHARE ROW 锁.
注意:这个模式同样比 SHARE ROW EXCLUSIVE 更有约束力;它阻塞所有并行的 SELECT FOR UPDATE 查询。
注意: 由语句 ALTER TABLE,DROP TABLE,VACUUM 执行时自动生效。这是最严格的约束锁,它与所有其他的锁模式冲突并且保护一个被锁定的表不被任何其他并行的操作更改。
注意: 一个不合格的 LOCK TABLE 同样要求这个锁模式(例如,一条没有显式锁模式选项的命令)。
RDBMS 锁定使用下面术语:
注意:如果没有声明 EXCLUSIVE 或 SHARE,假设为 EXCLUSIVE.锁存在于事务周期内.
注意:当在 SERIALIZABLE 隔离级别运行事务,而且你需要读取真实状态的数据时,你必须在执行任何 DML 语句(这时事务定义什么样的并行修改对它自己是可见的)之前运行一个 LOCK TABLE 语句。
继续上面的死锁(两个事务彼此等待)问题,你应该遵循两个通用的规则以避免死锁条件:
例如,如果一个应用更新行 R1 然后更新行 R2(在同一的事务里),那么第二个应用如果稍后要更新行 R1 时不应该更新行 R2(在同一事务里)。相反,它应该与第一个应用以相同的顺序更新行 R1 和 R2。
事务请求两个互相冲突的锁模式的前提:其中一个锁模式是自冲突的(也就是说,一次只能被一个事务持有)。如果涉及多种锁模式,那么事务应该总是最先请求最严格的锁模式。
这个规则的例子在前面的关于用 SHARE ROW EXCLUSIVE 模式取代 SHARE 模式的讨论中已经给出了。
注意: Postgres 不检测死锁,并将回卷至少一个等待的事务以解决死锁。
BEGIN WORK; LOCK TABLE films IN SHARE MODE; SELECT id FROM films WHERE name = 'Star Wars: Episode I - The Phantom Menace'; -- 如果记录没有返回则回卷 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;