为什么两个事务均为serializable级别时PostgreSQL不阻塞事务1?
问题现象说明
你观察到的调度时序如下:
两个事务均使用SERIALIZABLE隔离级别,T2先读取目标行数据,T1后续对同一行发起更新时没有被阻塞等待T2提交,和你预想的悲观阻塞逻辑不一致。
核心原因解释
这一现象是PostgreSQL的SERIALIZABLE隔离级别实现机制决定的:
- PostgreSQL没有采用传统的悲观两阶段锁(2PL)实现可序列化,而是使用可序列化快照隔离(SSI) 方案,核心是乐观并发校验而非提前阻塞。
- 事务运行过程中,PostgreSQL只会记录各事务的读写依赖关系,不会在操作阶段就对访问的资源加互斥锁阻止其他事务操作。你场景中T2读取行、T1更新行的操作会被记录为一条读写依赖,但两个事务可以继续并行执行,不会出现提前阻塞。
- 只有当两个事务都尝试提交时,PostgreSQL才会校验依赖关系是否存在会破坏可序列化性的异常,如果存在冲突,会回滚其中一个事务保证最终执行结果和某一串行执行的结果完全一致,满足
SERIALIZABLE隔离级别的语义要求。
补充说明
SSI的设计目的是在保证严格可序列化隔离的前提下,尽可能降低不必要的阻塞开销,提升高并发场景下的吞吐量,和传统串行排队的实现逻辑有本质区别,是造成你观察到的现象的根本原因。
内容的提问来源于stack exchange,提问作者matsrom
相关产品推荐
相关产品推荐

