# 4. 事务的执行过程@ACD

## introduction

事务最出名的特点, 就是那个"**要么执行/要么全都不执行(原子性)**", "**commit一定落盘(持久性)**". 这两个重要特性全是靠undo/redo/binlog三者的合作完成的.

## "事务改的数据" 是指什么数据?

事务具体怎么执行的方案是InnoDB负责的, InnoDB整出了一个叫做Buffer Pool的东西, 这种东西的原理是把磁盘上的页映射到内存里, 于是虽然磁盘读写比较慢, 但是内存读写却是相当的快 每次事务想要修改某个属性, 我们会先把这个对象从磁盘里加载到内存的Buffer Pool里, 然后我们开始执行事务内容

* 事务修改的时候直接修改到Buffer Pool, 加锁也是锁住Buffer Pool里的东西, 直到commit之前一直都只是在内存里
* 每执行一条语句, 这次修改都会直接改对应的内存页
  * 此操作会响应的生出一个相反的语句, 追加到undolog里面, 例如你执行了一条insert, 那么相应的就会有一条delete在undolog里
  * 此操作同样会被记录在redolog里, 我们记录下每一个操作的目的是为了在落盘之前如果宕机了, 就必须恢复之前执行的内容, 并把redolog设置成prepare状态

## 原子性是怎么做到的

**\[如果你想回滚]** : 也就是事务不要了, 这个时候我们需要将内存恢复原状, 因为这个内存是直接一一对应着磁盘的, 我们想要查盘每次都会先走这个内存, 因此不能就把这个内存搞脏了就放在这儿, 因此我们把undolog执行一遍, 将内存恢复原状

**\[如果你想commit]** : 这个时候我们的修改还停留在内存的buffer pool里, 我们首先写上binlog, 接着执行一条fsync将这些内存里的东西再一次性刷回硬盘里. 并把redolog的状态设置成commit, 代表这条数据已经在硬盘里了

## 如何保证提交一定落盘

**\[如果你还没到commit哪一步就crash了]** : 我们能在redolog里找到一些状态为prepare的语句, 这些语句应该被撤回, 操作undolog撤回

**\[如果你已经commit, 但是还没来得及落盘就crash了]** : 那么我们同样会在redolog里找到一些状态为prepare语句, 但于此同时binlog里也有这些语句:

* 如果binlog里有,  说明系统认为这些语句应该被执行
* 但于此同时redolog状态为prepare, 说明他们还没被执行, 因此执行
