其一种实现)都是事务的并发控制算法(手段),用于保证事务的隔离性(Isolation),即所有的并行事务被
以何种调度方式进行执行。我们都知道,事务是需要ACID四个属性的,前面我们只讨论了A和I,对C和D都没提
及,对于C而言,在我的上一篇文章中已经解释过,本质上它不属于数据库本身的责任(区别于CAP理论中的
C),因此本文不再赘述。而对于D而言,其表示持久性(Durability),意思是一个事务一旦提交成功,那么
事务产生的影响必须是持久化的、稳定不变的。显然,现实环境中(特别是分布式、大规模集群环境下),机
器硬件发生故障、内核崩溃和业务代码core dump是非常频繁的(后文我们统称为Crash),如何保证在任意时
间点发生Crash,机器重启(包括业务进程)后数据库还能恢复到之前的一致状态(已经提交的事务执行redo保
证事务的Durability,未提交的事务执行undo回滚保证事务的Atomicity),那么就是数据库中另一个重要的组
件:Crash Recovery 来保证了。
可能有人会有疑问了,既然2PC主要用来保证事务提交的Atomicity,Crash Recovery貌似也可以保证
Atomicity,那么它们之间有什么关系呢?其实,2PC更多的应于在分布式事务中,这里就要区分一下了。在分
布式事务中,如图2所示,通常把一个分布式事务称之为全局事务(由协调器Coordinator和参与者
Participants节点组成),而在每个参与者节点上也会存在本地的事务,通常称之为局部事务。全局事务一定是
建立在局部事务的基础上的,因为如果任何一个Participant上的局部事务都无法保证,那何谈全局分布式事务
呢?因此,本文讲的Crash Recovery主要是用来保证局部事务的Atomicity和Durability(但是有时候其实没有
必要分的非常清楚,因为一旦保证了局部事务,那么自然全局事务也就保证了)。
图2 全局事务与局部事务
steal、force、redo、undo
经过前文的论述,数据库中Crash Recovery模块主要用来保证(局部)事务的Atomicity和Durability。那么它
是怎么做到的呢?很多人肯定都知道redo log和undo log。但是很少有人能说清楚它们的作用分别是什么?只
需要redo log行不行?什么情况下两者都需要呢?其实,要搞清楚这些问题,还需要先介绍下数据库的缓存刷
新策略。为了保证数据库的Atomicity和Durability,数据库会先把数据的更新记录在日志中,再写行数据
(row data),最后提交。在事务提交时,日志是必须要写入稳定存储的。但是行数据呢?最理想的情况是在
事务提交那一刻写入稳定存储中,这种策略称之为force刷新策略,但是这个会严重影响性能(产生很多小的磁
盘随机io和写放大),因此现实中的数据库大多使用no-force策略(即事务提交的时候不会强制刷新行数据缓
冲page到磁盘)。现在,行数据可以在事务提交前和提交后写入稳定存储,在事务提交前就写入磁盘的情况称
之为steal策略(意思是在事务提交前,缓存中的一个行数据page被偷走了写入磁盘),相反,在事务提交前行
评论