Transactions (5-2) - Serializability Isolation - SSI & Summary

Day 6

强列建议阅读本文之前要先去看 Day 4 - Snapshot Isolation

3. 序列化快照隔离 SSI (Serializable Snapshot Isolation)

难道 序列化隔离 (serializable isolation) 跟良好效能是矛盾的吗?

在这里跟您介绍 序列化快照隔离 (Serializable Snapshot Isolation) ,一种比快照隔离多了一点开销的算法,但它提供了完整的序列化功能,它来自於 2009 年 Michael Cahill's 的博士论文

悲观 (Pessimistic) 和乐观 (Optimistic) 并发控制

二阶段锁 (Two-Phase Locking) 看上去可以被称为悲观的并发控制机制,悲观的大原则是说凡是有可能错的就一定会出错,也就是像 2PL 那样要取得 互斥模式 (exclusive mode) 锁才能写入资料,其他人最好还是乖乖等我!

连续执行 (Serial Execution) 更是悲到极致了,它本质上等同於每个 transaction 都得获取整个资料库的互斥锁才能做事情。

相比之下序列化快照隔离就是属於乐观的并发控制机制,乐观代表它不假设潜在的危害会发生,它希望一切都会好转;当一个 transaction 想要 commit 时,资料库才会检查是否有不好的事情在发生(例如隔离无效),如果有,则该 transaction 会中断且重试。

就像命名那样,序列化快照隔离的基础是快照隔离,所有的读取都是来自有一致性的资料库快照中 (Day 4 - Snapshot Isolation),而最大的不同是序列化快照隔离多新增了一个演算法,在写入期间去检测是否发生连续的冲突然後决定哪个 transaction 要被中断。

基於过时前提的决策

如同我们在 Day 5 提过的,快照隔离可能会发生 write skew ,其模式就是 查询-判断-写入,在 commit 时其原始查询结果可能 不再是最新的,因为该资料可能同时被其他 transaction 修改。

换一种方式来说,这些 transaction 是基於一种 前提 来执行,以 Day 5 - 医生 oncall 案例 来看,前提就是:目前正有 2 个医生在 oncall,尔後在 commit 时,这个前提可能就不是为真了。

但资料库怎麽知道应用程序对查询结果的判断逻辑为何呢?为了安全起见,资料库会假设所有的查询结果都可能都会被改变(查询结果 = 前提),意味者该 transaction 的写入可能会无效。

资料库必须检测 transaction 的前提是否过时,所以这里有 2 个状况需要考虑:

  • 检测从腐败 MVCC 物件版本读取的资料(未 commit 的写入发生在读取之前)。
  • 检测读取期间的写入(写入发生在读取之後)。

检查腐败的 MVCC 读取

回忆一下 MVCC 的机制,当 transaction 从一致的快照读取资料时,它会忽略其他未 commit 的 transaction 写入,如下图 7-10 (使用 Day 5 - 医生 oncall 案例),transaction 43 读取到的资料是 Alice on_call=true,因为 transaction 42 还没 commit,然而,当 transaction 43 想要 commit 时,transaction 42 已经 commit 了,这意味者 transaction 43 commit 会被忽略,transaction 管理者会注意到快照资料已被影响,且 前提 的值不再是最新的了。

检测读取期间的写入

现在来看第 2 个情况,如下图 7-11,transaction 42 和 43 都查询了 shift_id=1234 的班,如果这里有个 shift_id 的 index,资料库就会借用 index 进入点 1234 来记录 transaction 42 和 43 正在读取资料(如果没有 index 就会追踪在 table 等级中),其资料会保留到所有并发 transaction 都结束後才会清除。

当 transaction 写入到资料库时 ,它必须看一下 index 资料内是否也有正在读取的资料被影响,transaction 42 和 43 会彼此留意资料有可能不再是最新的,所以 transaction 43 想要 commit 时,transaction 42 已 commit 所以发生冲突,故 transaction 43 被中断了。

序列化快照隔离 (Serializable Snapshot Isolation) 的效能

乐观并发控制在有非常高度竞争时(多个 transaction 尝试存取相同物件)会表现的比较不好,代表了会有很多的片段 transaction 会需要被中断。

但是跟 二阶段锁 (Two-Phase Locking) 比起来,序列化快照隔离有个最大的优势就是 transaction 的写入不用阻档等待从其他 transaction 取得锁,就像快照隔离那样,写入跟读取不会互相影响,这个设计原则让查询延迟 (lantency) 变的可预测且变化较小,read-only 类型的查询可以从一致的快照读取资料而不需要取得任何锁,适合用在读取重的场景上。

而跟 连续执行 (Serial Execution) 比较呢?序列化快照隔离不必被限制上单一 CPU core 的吞吐量多少了。

影响序列化快照隔离效能最大的就是中断的比率,所以它当然也希望所有 transaction 都是短小精干(长时间只读不写的 transaction 也许 Ok);总而言之,它对缓慢 transaction 的敏感度远远小於 二阶段锁 跟 连续执行。

Summary

transaction 重要,但更重要的是挑选适合业务规则的资料库,希望 Day 1~Day 7 的 transaction 能帮助你们更了解一点。

总结这麽短是因为字数够了 XD


<<:  D6 第三周 (回忆篇)

>>:  [Day6]PHP运算符01

【Day 4】机器学习基本功(二) --- Regression

如何找到一个函式(function)?(上) 接下来会以李宏毅老师在影片中讲的例子来做说明整理。 寻...

成员 19 人:

撰写中 在求发展的道路上,又过了一日...... 这时,成员 19 人。 ...

Day20: EventEmitter

EventEmitter就是事件监听器,在Nodejs中这事件无所不在,都是基於程序中的对象会产生事...

[ Day 14 ] 佳评如潮的 React Hooks

今天总算进入到了 React.js 中大名鼎鼎的 React Hooks 这个章节了! 这样讲可能...

Day.13 Hash map

任何语言都会提供这一种资料结构,像Golang的map ex. var hash map[strin...