undo log 为什么需要落盘?

innodb 在更改数据行时会先记录undo log,现在有个问题 1.如果内存足够是不是可以不把undolog落盘,只在内存里面,这样在回滚的时候直…
关注者
32
被浏览
30,854

7 个回答

首先,mysql binlog并不是数据库日志,主要是用来复制,备份和恢复,和innodb的redo/undo log不是同一个层次的东西。

再来回答你的问题。由于innodb是delta存储结构,数据页中一直保持着最新的版本,undo记录着对应的更新前像。undo会写入rollback segment里,由于undo也是对页面的候改,记录undo这个操作本身也会有对应的redo。由于数据库的steal策略,事务在更新一个页面后,数据库是可以把未提交的数据刷入磁盘的,这时如果发生崩溃,恢复时数据库就需要从undo中找到数据库的更新前像。

考虑下面的情形,一个事务执行写元组x,y的操作:

write(x=a), 系统把元组x所在的页刷入磁盘, write(y=b), 系统崩溃...

系统恢复后要进行事务恢复,对应地这个事务需要回滚,事务需要从undo中找到x之前的值,如果事务不持久化undo(写这个undo操作的redo),那么对应事务就无法恢复到事务执行前的数据库状态,是不可恢复恢复的。

MySQL:数据库宕机以后恢复的过程?如何保证事务的ACID特性?

对于 实现了完整ACID事务,且事务提交前会覆盖写的db,都需要存储被覆盖的旧值供“读已提交”事务隔离时使用,并且crash recovery后对于未提交的事务需要把被覆盖的旧值还原为新值所以旧值需要落盘。 考虑到恢复需要逻辑线性序,所以需要把旧值组织成log。

综上,对于innodb,由于事务提交前会覆盖写,且在提交前利用锁和版本号让新值对“读未提交”隔离级别以上的事务不可见,故

1.需要存储旧值

2.旧值需要落盘

3.旧值落盘的结果需要组织成像log一样有基于事务id的逻辑时间序的东西。

于是就用了undo log来组织旧值。“如果在binlog提交前出现异常恢复时也不需要查找undolog,因为数据没有更改“ 这个说法疑似有误。