DbUpdateConcurrencyException与PostgreSQL 40001错误码的区别是什么
核心差异原因
两种错误分别对应不同层级的并发控制逻辑,触发链路完全不同:
1. Read Committed 隔离级别下 DbUpdateConcurrencyException 触发逻辑
- Read Committed 是 PostgreSQL 默认隔离级别,核心规则为事务内每次查询仅能看到其他已提交事务的修改,且不会长期持有行级读锁。
- 你的第一个事务初始查询实体时,该实体尚未被删除,查询成功拿到实体数据,后续进入耗时的S3上传流程,这段时间内第二个事务完成删除操作并提交。
- 等第一个事务执行UPDATE语句时,PostgreSQL会校验待更新行的状态,发现目标行已被其他已提交事务删除,最终返回0行受影响的执行结果。上层ORM(如EF Core)检测到预期更新行数和实际受影响行数不匹配时,会主动抛出
DbUpdateConcurrencyException,这是ORM层封装的业务类异常。
2. Serializable 隔离级别下 40001 错误触发逻辑
- Serializable 是最高隔离级别,PostgreSQL 通过*可序列化快照隔离(SSI)*实现该级别,核心要求是所有并发事务的执行结果,必须和这些事务按某一顺序串行执行的结果完全一致。
- SSI机制会全程监控事务间的读写依赖:第一个事务先执行了实体的读操作,第二个事务后续对同一实体执行了写(删除)操作并提交,这两个操作已经形成了违反串行一致性的读写依赖。
- PostgreSQL 内核检测到该冲突后,会直接判定第一个事务无法安全串行执行,不等第一个事务执行到UPDATE步骤,就会主动抛出错误码为
40001的序列化访问失败异常,这个异常是数据库内核原生抛出的,上层ORM会将其封装为携带错误码的InvalidOperationException,和行存在性校验没有直接关联,是数据库为了保证隔离性提前终止了冲突事务。
总结
两个异常本质都是并发竞争导致的,但触发阶段完全不同:
- Read Committed下是UPDATE执行后,ORM基于数据库返回的受影响行数判断抛出的并发更新异常
- Serializable下是事务执行过程中,数据库内核的SSI机制提前检测到串行冲突主动抛出的隔离性校验异常
内容的提问来源于stack exchange,提问作者GorgeousPuree
相关产品推荐
相关产品推荐

