“经典 SQL 92 用 事务调度 中三类现象描述四个隔离级别。P1 脏读指事务读取另一个尚未提交、后来可能中止的写;P2 不可重复读指同一事务两次读取同一项,期间另一事务提交修改或删除,结果…”
形式陈述 ​
设事务集合为
常用记号为
串行调度让一个事务终止后下一个才开始;并发调度则允许不同投影交错。调度是观察模型,不等同于线程真实同时运行:两个并行动作最终仍以某个事件次序进入该模型。若系统需要表达真正并列事件或弱内存偏序,必须另换语义,不能把一个随意排序当成已证明等价。
前缀调度可以含 pending 事务,完整调度则为每个出现的事务给出终止事件。良构性还要求一次读只返回一个值、终止后没有普通操作、同一事务不同时 commit 与 abort。性质若只检查已提交投影,应明确怎样处理 pending 和已中止事件,不能在反例出现后临时删除不利事务。
直觉
每个事务像一条保持自身字序的句子,调度把多条句子的字交织成一行。交织不能颠倒任何一句内部的字,却可能让一个事务在另一个提交前读到它的写。正是这条总记录,使“谁影响了谁”可以落成边与公式。
调度不先判好坏。它忠实记录一次可能正确、可能不可恢复、也可能不可串行化的执行。后续性质在同一个对象上逐层提问:冲突图是否有环,读者是否早于写者提交,崩溃时哪些事务已作出决定。
例子与边界
初值
r1(x)->5; w1(x,4);
r2(x)->4; w2(x,8);
r1(y)->7; w1(y,8);
c1; c2
两个事务各自的事件次序都未改变,所以这是一个调度。
若把
中止事件还带来另一层边界。调度可以记录
单版本解释中,
推论与应用
事务调度是 冲突可串行化、视图可串行化、SQL 隔离现象以及恢复性层级的共同输入。共享一个明确事件字母表能避免同一符号在一处表示逻辑写、另一处却表示物理页刷盘。
测试工具可从数据库 trace 归一化出候选调度,但墙钟时间相同不等于事件相同,缺失的读值也不能靠最终状态唯一补回。要把运行日志用于证明,必须说明事务标识、操作边界、提交结果及不确定顺序如何处理。
调度还可以作为并发测试的缩减对象:保留每个事务程序次序与真实冲突次序,折叠不影响数据库观察的线程内部计算。缩减是否可靠取决于投影定义;把触发器写、索引范围锁或约束查询漏掉,会制造一个比真实执行更温和的调度。
参考资料
- Philip A. Bernstein, Vassos Hadzilacos, and Nathan Goodman, Concurrency Control and Recovery in Database Systems, Addison-Wesley, 1987, Ch. 2。
- Christos H. Papadimitriou, The Theory of Database Concurrency Control, Computer Science Press, 1986, Chs. 2–3。
- Jim Gray and Andreas Reuter, Transaction Processing: Concepts and Techniques, Morgan Kaufmann, 1992, Chs. 6–7。