理解DELETE操作下的事务隔离:Postgres同事务删插数据时查询是否返回空
核心结论
只要DELETE和INSERT操作在同一个事务内执行并提交,其他独立查询事务永远不会查到该日期数据为空的中间状态。
原理说明
PostgreSQL的事务设计和MVCC(多版本并发控制)机制从根本上避免了这种中间状态暴露的问题:
- 事务具备原子性:同一事务内的所有修改是一个整体,对外要么全部可见,要么全部不可见,不存在只提交一半变更的情况。
- 默认隔离级别(读已提交
READ COMMITTED)下,所有读操作都是快照读,只能读取到其他事务已经提交完成的变更,永远不会读取到未提交的中间修改。 - 你在事务内执行DELETE时,修改仅对当前事务可见,其他事务此时查询2021-09-08的数据,还是DELETE执行前的旧数据;等你执行完INSERT、提交整个事务后,其他事务才会同时看到DELETE和INSERT的结果,直接拿到新插入的当日数据,完全感知不到中间的删插过程。
可能返回空结果的唯一场景
只有当你把DELETE和INSERT拆分为两个独立的事务提交时,才会出现查询为空的问题:DELETE事务先提交,INSERT事务还未提交的间隙,其他查询就能读到该日期数据被清空的状态。这个是业务代码拆分事务的逻辑问题,和数据库本身的事务机制无关。
业务优化建议
如果你的日数据覆盖场景频率较高,除了现有同一事务删插的方案,还可以用PostgreSQL的INSERT ON CONFLICT语法做Upsert操作,替代先删后插的逻辑,锁粒度更小、执行效率更高,也能达到全量覆盖当日数据的效果。
内容的提问来源于stack exchange,提问作者BrainPermafrost
相关产品推荐
相关产品推荐

