PostgreSQL锁模式冲突含义及RowExclusiveLock阻塞疑问
PostgreSQL锁模式冲突疑问与解答
背景
PostgreSQL官方文档中的锁模式表显示:ROW EXCLUSIVE锁模式与SHARE、SHARE ROW EXCLUSIVE、EXCLUSIVE、ACCESS EXCLUSIVE锁模式冲突,但不与自身冲突。
以下通过两个实操案例提出疑问:
案例1
同时启动事务T1和T2:
T1执行:
my_db=# begin; BEGIN my_db=*# update t set color = 'green' where id = 2; UPDATE 1
T2执行:
my_db=# begin; BEGIN my_db=*# update t set color = 'blue' where id = 2;
此时T2被阻塞。查询表t的锁信息仅见RowExclusiveLock和AccessShareLock模式,但根据锁模式表,RowExclusiveLock不与自身冲突。
案例2
重新启动事务T1和T2:
T1执行:
my_db=# begin; BEGIN my_db=*# alter table t alter column color TYPE varchar(400); ALTER TABLE
T2执行:
my_db=# begin; BEGIN my_db=*# update t set color = 'black' where id = 2;
T2同样被阻塞,此时查询可见AccessExclusiveLock,而RowExclusiveLock与该模式冲突。
核心疑问
- PostgreSQL中“锁模式与另一锁模式冲突”具体指什么?
- 为何
RowExclusiveLock不与自身冲突,却会阻塞另一事务?
解答
1. 锁模式冲突的定义
PostgreSQL中,锁模式冲突指的是:当一个事务已持有某一数据库对象(表、行等)的某类锁时,若另一个事务请求同一对象的另一类锁,且两类锁的操作意图互斥,则后一个事务会被阻塞,直到前一个事务释放所持锁。简单说就是两种锁的操作不能同时在同一对象上执行,必须串行处理。
2. RowExclusiveLock不冲突却阻塞的原因
问题出在混淆了表级锁和行级锁的作用范围:
- 案例1中,两个事务的
update确实都在表t上持有表级的RowExclusiveLock,这类表级锁之间确实不冲突——这意味着多个事务可以同时对同一表持有该类表级锁(比如同时更新表中不同行)。但真正导致T2阻塞的是行级排他锁:T1执行update时,会对id=2的行加上行级的排他锁,T2要修改同一行,必须请求该行的排他锁,而行级排他锁是互斥的,所以T2被阻塞。 - 表级锁的冲突规则和行级锁的互斥逻辑是独立的两个层面,不能混为一谈。
内容的提问来源于stack exchange,提问作者Anton Romanov
相关产品推荐
相关产品推荐

