PHP实战中知识总结 / PgSQL - 锁机制

PostgreSQL中有两类锁:表级锁和行级锁。当要查询、插入、更新、删除表中数据时,首先要获得表级锁,然后获得行级锁。

一、表级锁

锁模式解释
Access Share只与Access Exclusive锁模式冲突。
查询命令(Select command)将会在它查询的表上获取Access Shared锁,一般地,任何一个对表上的只读查询操作都将获取这种类型锁。
Row Share与Exclusive和Access Exclusive锁模式冲突。
Select for update和Select for share命令将获得这种类型锁,并且所有被引用但没有for update 的表上会加上Access Shared锁。
Row Exclusive与Share,Shared Row Exclusive,Exclusive,Access Exclusive模式冲突。
Update/Delete/Insert命令会在目标表上获得这种类型的锁,并且在其它被引用的表上加上Access Share锁,一般地,更改表数据的命令都将在这张表上获得Row Exclusive锁。
Share Update ExclusiveShare Update Exclusive,Share,Share Row Exclusive,Exclusive,Access exclusive模式冲突,这种模式保护一张表不被并发的模式更改和Vacuum。
Vacuum(without full),Analyze 和 Create index concur-ently命令会获得这种类型锁。
Share与Row Exclusive,Shared Update Exclusive,Share Row Exclusive,Exclusive,Access exclusive锁模式冲突,这种模式保护一张表数据不被并发的更改。
Create index命令会获得这种锁模式。
Share Row Exclusive与Row Exclusive,Share Update Exclusive,Shared,Shared Row Exclusive,Exclusive,Access Exclusive锁模式冲突。
任何PostgreSQL命令不会自动获得这种类型的锁。
Exclusive与ROW Share , Row Exclusive, Share Update Exclusive, Share , Share Row Exclusive, Exclusive, Access Exclusive模式冲突,这种锁模式仅能与Access Share 模式并发,换句话说,只有读操作可以和持有Exclusive锁的事务并行。
任何PostgreSQL命令不会自动获得这种类型的锁。
Access Exclusive与所有模式锁冲突(Access Share,Row Share,Row Exclusive,Share Update Exclusive,Share , Share Row Exclusive,Exclusive,Access Exclusive),这种模式保证了当前只有一个人访问这张表;ALTER TABLE,DROP TABLE,TRUNCATE,REINDEX,CLUSTER,VACUUM FULL 命令会获得这种类型锁,在Lock table 命令中,如果没有申明其它模式,它也是默认模式。

二、表级锁的冲突矩阵

“N”表示这两种表冲突,也就是不同的进程不能同时持有这两种锁。

请求的锁模式(已申请到的锁模式)Access ShareRow ShareRow ExclusiveShare Update ExclusiveShareShare Row ExclusiveExclusiveAccess Exclusive
Access ShareYYYYYYYN
Row ShareYYYYYYNN
Row ExclusiveYYYYNNNN
Share Update ExclusiveYYYNNNNN
ShareYYNNNNNN
Share Row ExclusiveYYNNNNNN
ExclusiveYNNNNNNN
Access ExclusiveNNNNNNNN

三、表级锁对应的操作

锁类型对应的数据库操作
Access Shareselect
Row Shareselect for update, select for share
Row Exclusiveupdate,delete,insert
Share Update Exclusivevacuum(without full),analyze,create index concurrently
Sharecreate index
Share Row Exclusive任何Postgresql命令不会自动获得这种类型的锁
Exclusive任何Postgresql命令不会自动获得这种类型的锁
Access Exclusivealter table,drop table,truncate,reindex,cluster,vacuum full

四、行级锁

行级锁模式只有两种,分别是共享锁和排他锁,或者说是读锁或写锁。由于多版本的实现,实际读取行数据时,并不会在行上执行任何锁。

特定行上的行级锁是在行被更新的时候自动请求的(或者被删除时或标记为更新)。 锁一直保持到事务提交或者回滚。行级锁不影响对数据的查询;它们只阻塞对同一行的写入。 要在不修改某行的前提下请求在该行的行级锁,用 SELECT FOR UPDATE 选取该行。请注意一旦我们请求了特定的行级锁,那么该事务就可以多次对该行进行更新而不用担心冲突。

五、行级锁的冲突矩阵

解释
FOR UPDATEFOR UPDATE会导致由SELECT语句检索到的行被锁定,就好像它们要被更新。这可以阻止它们被其他事务锁定、修改或者删除,一直到当前事务结束。也就是说其他尝试UPDATE、DELETE、SELECT FOR UPDATE、SELECT FOR NO KEY UPDATE、SELECT FOR SHARE或者SELECT FOR KEY SHARE这些行的事务将被阻塞,直到当前事务结束。反过来,SELECT FOR UPDATE将等待已经在相同行上运行以上这些命令的并发事务,并且接着锁定并且返回被更新的行(或者没有行,因为行可能已被删除)。不过,在一个REPEATABLE READ或SERIALIZABLE事务中,如果一个要被锁定的行在事务开始后被更改,将会抛出一个错误。
FOR NO KEY UPDATE行为与FOR UPDATE类似,不过获得的锁较弱:这种锁将不会阻塞尝试在相同行上获得锁的SELECT FOR KEY SHARE命令。任何不获取FOR UPDATE锁的UPDATE也会获得这种锁模式。
FOR SHARE行为与FOR NO KEY UPDATE类似,不过它在每个检索到的行上获得一个共享锁而不是排他锁。一个共享锁会阻塞其他事务在这些行上执行UPDATE、DELETE、SELECT FOR UPDATE或者SELECT FOR NO KEY UPDATE,但是它不会阻止它们执行SELECT FOR SHARE或者SELECT FOR KEY SHARE。
FOR KEY SHARE行为与FOR SHARE类似,不过锁较弱:SELECT FOR UPDATE会被阻塞,但是SELECT FOR NO KEY UPDATE不会被阻塞。一个键共享锁会阻塞其他事务执行修改键值的DELETE或者UPDATE,但不会阻塞其他UPDATE,也不会阻止SELECT FOR NO KEY UPDATE、SELECT FOR SHARE或者SELECT FOR KEY SHARE。
要求的锁模式(当前的锁模式)FOR KEY SHAREFOR SHAREFOR NO KEY UPDATEFOR UPDATE
FOR KEY SHAREYYYN
FOR SHAREYYNN
FOR NO KEY UPDATEYNNN
FOR UPDATENNNN

PHP实战中知识总结