LOCK [ TABLE ] name LOCK [ TABLE ] name [, ...] IN lockmode MODE 这里 lockmode 可以是下列之一∶ ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE | SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE
要锁定的现存表的名字(可以有模式修饰).
注意: 这个锁模式对被查询的表自动生效。
这是最小限制的锁模式,只与 ACCESS EXCLUSIVE 模式冲突。 它用于保护被查询的表免于被并行的 ALTER TABLE, DROP TABLE 和 VACUUM FULL 对同一表操作的语句修改。
注意: 任何 SELECT...FOR UPDATE 语句执行时自动生效。
与 EXCLUSIVE 和 ACCESS EXCLUSIVE 锁模式冲突。
注意: 任何 UPDATE, DELETE和 INSERT 语句执行时自动生效。
与 SHARE, SHARE ROW EXCLUSIVE, EXCLUSIVE 和 ACCESS EXCLUSIVE 模式冲突。
Note: 由 VACUUM (没有 FULL) 自动要求.
和SHARE UPDATE EXCLUSIVE,SHARE,SHARE ROW EXCLUSIVE, EXCLUSIVE 和 ACCESS EXCLUSIVE 模式冲突.这个模式保护一个表 不被并行的(事务进行)模式修改和VACUUM.
注意: 任何 CREATE INDEX 语句执行时自动附加。 共享锁住整个表.
与 ROW EXCLUSIVE,SHARE UPDATE EXCLUSIVE, SHARE ROW EXCLUSIVE,EXCLUSIVE 和 ACCESS EXCLUSIVE 模式冲突。这个模式防止一个表的并行数据更新。
注意: 这个模式类似 EXCLUSIVE MODE,但是允许其他事务的 ROW SHARE 锁.
与 ROW EXCLUSIVE,SHARE UPDATE EXCLUSIVE, SHARE,SHARE ROW EXCLUSIVE,EXCLUSIVE 和 ACCESS EXCLUSIVE 模式冲突。
注意: 这个模式同样比 SHARE ROW EXCLUSIVE 更有约束力. 它阻塞所有并行的 ROW SHARE/SELECT... FOR UPDATE 查询。
与 ROW SHARE,ROW EXCLUSIVE,SHARE UPDATE EXCLUSIVE, SHARE,SHARE ROW EXCLUSIVE,EXCLUSIVE 和 ACCESS EXCLUSIVE 模式冲突。 这个模式只允许并发的 ACCESS SHARE,也就是说只有从表中读取数据 可以和一个持有这个锁模式的事务并发执行.
注意: 由语句 ALTER TABLE, DROP TABLE,VACUUM FULL 执行时自动生效。这是最严格的约束锁,它 保护一个被锁定的表不被任何其他并行的操作更改。
注意: 一个不合格的 LOCK TABLE 同样要求这个锁模式 (例如,一条没有显式锁模式选项的命令)。
与所有锁模式冲突.
LOCK TABLE 控制一次事务的生命期内对某表的并行访问. PostgreSQL 在可能的情况下尽可能使用最小约束的锁模式。 LOCK TABLE 在你需要时提供更有约束力的锁。
RDBMS 锁定使用下面术语:
一个排它锁禁止其它同类型的锁获得批准.(注意∶ROW EXCLUSIVE 模式 并不完全遵循这个命名规则,因为它是在表一级共享的;它只是相对于 要更新的行而言是排它的.)
共享锁允许其它(事务)也持有同类型锁,但是禁止对应的 EXCLUSIVE 锁获得批准.
锁定表结构.
锁定独立的行.
例如,假设一个应用在 READ COMMITED 隔离级别上运行事务, 并且它需要保证在表中的数据在事务的运行过程中都存在。要实现这个目的,你 可以在查询之前对表使用 SHARE 锁模式进行锁定。这样将保护数据不被 并行修改并且为任何更进一步的对表的读操作提供实际的当前状态的数据, 因为 SHARE 锁模式与任何写操作需要的 ROW EXCLUSIVE 模式冲突,并且你的 LOCK TABLE name IN SHARE MODE 语句将等到所有并行的写操作提交或回卷后才执行。 因此,一旦你获得该锁,那么就不会存在未提交的写操作.
注意: 当运行在 SERIALIZABLE 隔离级别并且你需要读取真实状态的数据时, 你必须在执行任何DML语句 之前运行一个 LOCK TABLE 语句。 一个可串行化事务的数据视图将在其第一个DML语句开始的时候冻结住. 稍后的 LOCK 将仍然阻止并发的写 --- 但它不能保证 事务读取的东西对应最近提交的数值。
除了上面的要求外,如果一个事务准备修改一个表中的数据, 那么应该使用 SHARE ROW EXCLUSIVE 锁模式以避免死锁情况(当两个 并行的事务试图以 SHARE 模式锁住表然后试图更改表中的数据时, 两个事务(隐含的)都需要 ROW EXCLUSIVE 锁模式,而此模式与并行的 SHARE 锁冲突)。
继续上面的死锁(两个事务彼此等待)问题, 你应该遵循两个通用的规则以避免死锁条件:
事务应该以相同的顺序对相同的对象请求锁。
例如,如果一个应用更新行 R1 然后更新行 R2(在同一的事务里), 那么第二个应用如果稍后要更新行 R1 时不应该更新行 R2(在 同一事务里)。相反,它应该与第一个应用以相同的顺序更新行 R1 和 R2。
事务请求两个互相冲突的锁模式的前提:其中一个锁模式是自冲突的 (也就是说,一次只能被一个事务持有)。 如果涉及多种锁模式,那么事务应该总是最先请求最严格的锁模式。
这个规则的例子在前面的关于用 SHARE ROW EXCLUSIVE 模式取代 SHARE 模式的讨论中已经给出了。
注意: PostgreSQL 的确检测死锁, 并将回卷至少一个等待的事务以解决死锁。
演示在往一个外键表上插入时在有主键的表上使用 SHARE 的锁:
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;
在SQL92里面没有LOCK TABLE ,可以使用 SET TRANSACTION 来声明当前事务的级别. 我们也支持这个,参阅 SET TRANSACTION 获取详细信息。
除了ACCESS SHARE,ACCESS EXCLUSIVE,和SHARE UPDATE EXCLUSIVE 锁模式外, PostgreSQL 锁模式和 LOCK TABLE 语句都与那些在 Oracle(TM) 里面的兼容。