You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

事务隔离级别:脏写与丢失更新的定义差异及判定疑问

你的理解偏差核心

你推导错误的根源有两个:

  1. 搞反了两类异常定义里两个写操作的先后顺序
  2. 忽略了脏写定义隐含的「两个写操作发生时,双事务均处于活跃未提交状态」的时序约束

先把论文中两个异常的操作序列约束拆解清楚:

  • 脏写定义序列:w1[x]...w2[x]...((c1 or a1) and (c2 or a2) in any order)
  • 丢失更新定义序列:r1[x]...w2[x]...w1[x]...c1

注意脏写要求同数据的写顺序是T1先写、T2后写,且T2执行写操作时,T1和T2自身都还没执行提交/回滚;而丢失更新里的同数据写顺序是T2先写、T1后写,完全没有对T2写操作之后的提交时机做任何约束。光写顺序这一点,就决定了两类异常不存在严格的包含关系,阻止脏写不可能覆盖所有丢失更新场景。

两类异常的判定边界

你可以通过明确的判定条件区分二者,不存在模糊地带:

脏写判定(需同时满足所有条件)

  • 两个活跃(未提交/未回滚)的事务,先后对同一条数据x执行写操作
  • 写顺序固定为:事务A先写x,事务B后覆盖写x
  • 事务B执行写操作的时点,事务A尚未提交/回滚,事务B自身也尚未提交/回滚

脏写的核心危害是会导致事务回滚时无法确定正确的数据版本:比如T1写x、T2写x之后T1回滚,数据库没法判断x应该回滚到T1写之前的版本,还是保留T2写入的版本,会破坏事务的原子性保证。

丢失更新判定(满足即可)

  • 事务T1首先读取了数据x的值,准备基于读到的值做计算后更新x
  • 在T1完成读x、执行自身对x的写操作之间,任意其他事务T2对x执行了写操作(不限制T2写之后是否提交、什么时候提交)
  • T1后续基于最初读到的x旧值完成计算,写入x并直接覆盖了T2之前写入的结果
  • T1最终提交

丢失更新的核心危害是会导致并行的读改写操作出现覆盖,业务逻辑上的更新操作被静默丢弃,和写操作发生时事务是不是活跃没有必然关系。

无脏写的丢失更新典型场景

你看到的技术文章里标注的「T2在T1写入x前就已提交,因此无脏写」是非常普遍的丢失更新场景,时序如下(以账户余额扣减为例):

  1. r1[x=100]:T1读取账户x余额为100,要扣减10元,计算得到待写入值90
  2. r2[x=100]:T2读取账户x余额为100,要扣减20元,计算得到待写入值80
  3. w2[x=80]:T2写入扣减后的余额80
  4. c2:T2提交,修改正式持久化
  5. w1[x=90]:T1基于之前读到的旧值100,写入计算得到的90,直接覆盖了T2已经提交的80
  6. c1:T1提交

对照判定条件可以看到:

  • 该场景不满足脏写要求:写顺序是T2先写、T1后写,且T1写x时T2已经提交完成,根本不是活跃状态,确实不存在脏写
  • 该场景完全符合丢失更新要求:T1先读x,T2在T1读之后写x,T1后续用旧值计算的结果覆盖了T2的写入,最终T2扣减20元的操作完全丢失,账户余额错误。

少数场景下两类异常可能同时出现,但这只是时序重叠的特例,不代表二者存在因果防护关系。


内容的提问来源于stack exchange,提问作者Patrick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 06:18:24