事务调度中盲写场景的可恢复性困惑解析
事务调度中盲写的可恢复性问题
不可恢复调度示例
以下调度属于不可恢复调度:
T1 T2 R(A) W(A) R(A) W(A) Commit Commit
若故障发生在两次Commit之间,T2已提交无法回滚,而T1后续失败回滚时,T2基于T1未提交的A值做出的修改已持久化,会导致数据库状态不一致。
调整后的可恢复调度
将调度修改为如下形式后,即成为可恢复调度:
T1 T2 R(A) W(A) R(A) W(A) Commit Commit
- 若故障发生在T1 Commit之前:可回滚T1和T2的所有操作,不会留下不一致状态。
- 若故障发生在两次Commit之间:只需回滚T2并重新执行即可,T1已提交的修改是可靠的,T2重新执行时基于正确的A值操作。
盲写调度的可恢复性疑惑
根据可恢复调度的标准定义:对于任意一对事务Ti和Tj,若Tj读取了Ti之前写入的数据项,则Ti的Commit操作需出现在Tj的Commit操作之前。
按此定义,以下包含盲写的调度属于可恢复调度:
T1 T2 R(A) W(A) W(A) Commit Commit
但存在疑问:若故障发生在两次Commit之间,T2已提交无法回滚,仅回滚T1并重新执行的话,数据库最终会保留T1的W(A)值,而原本意图是存储T2的W(A)值,为何该调度仍属于可恢复调度?
核心解惑:盲写与可恢复性的关系
可恢复调度的核心目标是避免因“读脏数据”导致的已提交事务无法撤销的不一致问题,其约束仅针对存在“读依赖”的场景——即Tj读取了Ti未提交的数据。
在上述盲写调度中,T2并未读取T1写入的A值,而是直接覆盖了A的内容,两者之间不存在读依赖:
- 当T1在T2提交后失败回滚时,T1的W(A)属于未提交操作,原本就不会被持久化到数据库(数据库只保留已提交事务的修改),此时数据库中实际保留的是T2提交的W(A)值。
- 重新执行T1时,会基于T2已提交的A值进行操作,这完全符合事务的执行逻辑,不会产生不一致。
简言之,可恢复调度的规则不约束盲写场景,因为盲写不存在读脏数据的依赖,所以该调度满足可恢复调度的定义。
内容的提问来源于stack exchange,提问作者Kushagr Jaiswal
相关产品推荐
相关产品推荐

