ACID 的原子性和隔离性能让使用端在一个 transaction 下有多次写入,并能一次操作多个物件 (Object)。
物件可以指一笔资料、一个文件 (docuemnt) 或一笔记录 (record)。
如下图 7-3 的多物件修改那样,多物件修改通常需要资料保持同步,User 1 替收件 ID 2 新增了一笔 email 资料,则 ID 2 的信箱未读数量就需要 +1;但 User 2 的体验就很奇怪了,明明 ID 2 的 email 是未读的,但信箱的未读数却是 0 !?
此时 隔离性 就能避免这种情形了,隔离性能保证 transactoin 不会互相影响,所以 User 2 要嘛只会读更新前或後的资料,不会有那种不一致的一半资料。
下图 7-3 则是展示了另外一种多物件操作时会发生的情况,不幸的更新信箱时爆炸了,在 原子性 的保证下,整个 transaction 会中断,已新增的 email 会 rollback 。
多物件操作需要某种方法检测读取跟写入是属於同一个 transaction,在 RDB 中,一个典型的方法就是在同一个 TCP 连线下,任何 BEGIN TRANSACTION
和 COMMIT
之间都视为同一个 transaction。
这不是个很理想的方法喔,因为 TCP 有断线的可能,如果断在 commit 送出後使用者未收到结果时,工程师会不知道到底成功 commit 了没有,解法是给 transcation 一个识别 ID,使该 transaction ID 不绑定在特定的 TCP 连线上,这个主题应该会在 Day 28~29 时聊到。
原子性和隔离性也能运用在单物件操作上,举例来说,假设你正在资料库更新一个 20 KB 的 JSON document (value = JSON):
这些状况如同多物件操作的问题那样令人困惑,所以大多数的储存引擎在单一节点上的单物件操作都会支援原子性和隔离性 (包含 key-value 类型资料),原子性可使用 log 来恢复资料(B-Tree 的可靠性),而隔离性就可使用锁 (lock) ,资料更新後就倚靠之前讲过的 replication 机制去同步资料。
有些 No-SQL 爱好者或许会认为:资料库在单物件操件上有支援 ACID,加上它们避免 更新遗失 (lost update) 的方法是使用 比较并交换 (Compare-and-set),这样就像个轻量化的 transaction 了!
PS 1: Day 5 会细谈有哪些避免 更新遗失 (lost update) 的方法。
PS 2: 该书作者认为,transaction 就是一个机制能把多物件操作视为一个执行,所以希望大家不要在用奇怪的术语误导大家了XD
但是在现实世界中,单物件操作上还是会遇到需要 transaction 的场景,例如在 document 资料模型上,尽管你做了 denormalized ,还是有可能会有像上图 7-2 那样,你需要同时更新 email 和 mailbox 等不同 document 资料的时候,有 transaction 是不是就能让工程师少烦恼一点了呢?
有一好没二好啦,有很多分布式储存引擎弃用了多物件操作 transaction(很难在跨分区上实现),但它给了我们强大的高可用性和高性能,那这样分布式 transaction 就没希望了吗?我们应该会在 Day 20 谈谈如何实现分布式 transaction。
今天讲甚麽 今天不讲技术,讲讲打满二十天给我的心得。 二十天说长不长,说短不短。原本以为自己把参赛的...
让我们再来看一遍消费流程: 订单建立⇒交易付款⇒信用卡付款.ATM转帐.(超商付款)⇒付款成功 买方...
我第一次听过程序竞赛时是在我刚进到国三的下学期。 在这之前我对於程序的相关经验除了国中科展学的 PH...
今天来补充一下”快速面试”还要再补充的地方,现在回想还是怕… 有一家厂商满特别的,一开始面试直接问...
执行推论(C/C++ + Arduino IDE + MCU) 书接上回[Day 12] tinyM...