事务实现原理

Posted by 皮皮潘 on 12-07,2021

事务的核心为ACID:原子性,一致性,隔离性,持久性

其中,隔离性是由锁和MVCC机制实现的,这在之前的一篇博客中已经给出,原子性和持久性是由Redo Log实现的,一致性是由Undo Log实现的

Redo Log是物理日志,Undo Log和Binlog都是逻辑日志,物理日志和逻辑日志的区别在于:前者的存储内容是数据库中特定记录的变更,即描述某一个Page的修改操作(一条更新请求对应的初始值以及更新值),它是一个幂等的操作可以反复重放;后者的存储内容是存储事务的一个操作(事务中的UPDATE、DELETE以及INSERT操作),它不是一个幂等的操作不可以反复重放

在具体的实现中,InnoDB是唯一支持事务的数据库存储引擎,它使用Redo Log实现了事务的持久性:一旦Commit了那么在数据库崩溃的情况下,可以使用Redo Log恢复没有入库的数据,另外使用Undo Log实现了事务的一致性:在事务回滚的时候使用Undo Log来撤销之前的操作,总而言之,Redo用来恢复数据,Undo用来回滚数据,另外MVCC也是基于Undo Log来实现的,Undo Log相当于记录了数据的多个版本。除此之外,Redo Log是物理日志,Undo Log是逻辑日志,除了数据本身的修改外,Undo Log也会生成对应的Redo Log,因此在数据库崩溃恢复的时候,会先从备份点执行所有的Redo Log(包括数据修改和Undo Log的恢复),然后对于没有Commit的事务执行对应的Undo Log。Redo Log和Undo Log都是Log Ahead从而保证持久性。

除了数据库引擎本身的日志之外,MySQL本身也会记录对应的日志:binlog,不同于Redo Log每次数据修改都会将log从buffer刷入磁盘,binlog仅仅在事务提交的时候才会将log刷入磁盘,且该刷入是顺序的。binlog有三种格式:row类似物理日志,statement类似逻辑日志,mixed前两者的混合。相较于Redo和Undo Log,binlog的目的更多是为了实现主从复制和一定程度上的崩溃恢复,但是不同于前者会在数据库重启时自动恢复,后者需要手动通过命令行的方式恢复

XA事务主要实现了一个应用,多个数据库的分布式事务,它的核心在于二阶段提交(Prepare + Commit)以及每个数据库的线性的事务隔离模式,其中往往由应用既充当应用本身又充当协调者的角色,后者一般由框架实现