PG的锁(一)
一、表级锁
1.1 表级锁模式
常见锁模式以及应用场景:
ACCESS SHARE :select操作获取该模式锁资源,通常情况下所有只读取不修改表的查询都会获取该模式锁资源
ROW SHARE : select for update 和 select for share 命令获取该模式锁资源
ROW EXCLUSIVE : DML操作通过会获取该模式锁资源,通常情况下任何需要修改表数据的操作都会持有该模式锁资源
SHARE UPDATE EXCLUSIVE :对于 vacuum(非full)、create index concurrnetly、reindex concurrently、create statistics、alter index相关、alter table相关操作会持有该模式锁资源,该模式锁资源主要是为了范围并发对同一张表DDL变更以及vacuum操作
SHARE : create index (非concurrently)操作会持有该模式锁资源,该模式锁资源可阻止并发对表的创建索引操作
SHARE ROW EXCLUSIVE : cerate trigger、一些alter table操作会持有该模式锁资源
EXCLUSIVE : refresh materialized view concurrently操作会持有该模式锁资源
ACCESS EXCLUSIVE :lock table模式锁定模式,drop table、truncate、reindex、 cluster、vacuum full、refresh materialized view (without concurrently) 还有一些alter table、alter index操作需要获取该模式锁资源,该模式锁资源保证了持有者唯一访问表。
1.2 表级锁兼容性
锁模式 | ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE | SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE |
ACCESS SHARE | X | |||||||
ROW SHARE | X | X | ||||||
ROW EXCLUSIVE | X | X | X | X | ||||
SHARE UPDATE EXCLUSIVE | X | X | X | X | X | |||
SHARE | X | X | X | X | X | |||
SHARE ROW EXCLUSIVE | X | X | X | X | X | X | ||
EXCLUSIVE | X | X | X | X | X | X | X | |
ACCESS EXCLUSIVE | X | X | X | X | X | X | X | X |
二、行级锁
2.1 行级锁模式
常见锁模式以及应用场景:
FOR UPDATE :对于所有的for update操作,对于被检索的数据行进行for update行锁锁定,阻止其他事务对持有for update行锁记录进行更新。在RR和SERIALIZABLE隔离级别下,如果一个被for update锁定的行在当前事务开始后被修改,该事务会抛出异常报错。对于update、delete操作同样需要获取for update行模式锁
FOR NO KEY UPDATE :与for update行模式锁类似,但是其锁范围相对较弱。对于不需要获取 for update 行锁资源的所有delete、update操作都会持有该行模式锁。在RR和SERIALIZABLE隔离级别下,如果一个被for update锁定的行在当前事务开始后被修改,该事务会抛出异常报错。
FOR SHARE : 对于检索记录添加share lock,该模式锁资源会阻塞其他事务对持有锁记录进行delete、update、select for update、for no key update,但允许其他事务并发添加for share或者for key share
FOR KEY SHARE : 相对于for share,该模式锁相对更加弱一些,他允许其他事务并发持有for no key update模式锁资源
2.2 行级锁兼容性
锁模式 | FOR KEY SHARE | FOR SHARE | FOR NO KEY UPDATE | FOR UPDATE |
FOR KEY SHARE | X | |||
FOR SHARE | X | X | ||
FOR NO KEY UPDATE | X | X | X | |
FOR UPDATE | X | X | X | X |
2.3 锁测试
1、RR隔离级别下 for update 测试
事务一 | 事务二 |
- | START TRANSACTION ISOLATION LEVEL REPEATABLE READ; |
- | select id from t1 where id2=327;//id=2,6240 |
START TRANSACTION ISOLATION LEVEL REPEATABLE READ; | - |
- | update t1 set info ='aaaaaaaaa' where id=2; |
select * from t1 where id2=327 for update;//被夯住 | - |
- | commit; |
select for update抛出异常报错“ERROR: could not serialize access due to concurrent update” |
for no key update操作也会出现相同的报错提示。
三、页面级锁
page-level share/exclusive : 控制对shared buffer pool中数据页的读写操作,在获取对应需要查询或者更新的行记录后会立即释放页面级别锁。应用开发者通常不需要关心页级锁。