2.5 undo log的生命周期
1.简要生成过程
以下是undo+redo事务的简化i过程
假设有2个数值,分别为A=1和B=2,然后将A修改为3,B修改为4
1 - start transaction ; 2.记录A=1到undo log; 3 - update A = 3; 4.记录A=3 到redo log; 5.记录B=2到undo log; 6 - update B = 4; 7.记录B =4到redo log; 8.将redo log刷新到磁盘 9 - commit
在1-8步骤的任意一步系统宕机,事务未提交,该事务就不会对磁盘上的数据做任何影响
如果在8-9之间宕机,恢复之后可以选择回滚,也可以选择继续完成事务提交,因为此时redo log已经持久化
若在9之后系统宕机,内存映射中变更的数据还来不及刷回磁盘,那么系统恢复之后,可以根据redo log把数据刷回磁盘
只有Buffer Pool的流程:
有了Redo Log和Undo Log之后:
在更新Buffer Pool中的数据之前,需要先将该数据事务开始之前的状态写入Undo Log中。假设更新到一半出错了,就可以通过Undo Log来回滚到事务开始前。
2. 详细生成过程
对于InnoDB引擎来说,每个行记录除了记录本身的数据之外,还有几个隐藏的列:
DB_ROW_ID:如果没有为表显式的定义主键,并且表中也没有定义唯一索引,那么InnoDB会自动为表添加一个row_id的隐藏列作为主键
DB_TRX_ID:每个事务都会分配一个事务ID,当对某条记录发生变更时,就会将这个事务的事务ID写入trx_id中
DB_ROLL_PTR;回滚指针,本质上就是指句undo log的指针
当我们执行INSERT时:
begin; INSERT INTO user (name) VALUES ("tom");
插入的数据都会生成一条insert undo log,并且数据的回滚指针会指向它。undo log会记录undo log的序号、插入主键的列和值…。那么在进行rollback的时候,通过主键直接把对应的数据删除即可。
当我们执行UPDATE时:
对于更新的操作会产生update undo log,并且会分更新主键的和不更新主键的,假设现在执行:
UPDATE user SET name= "Sun" WHERE id=1;
这时会把老的记录写入新的undo log,让回滚指针指向新的undo log,它的undo no是1,并且新的undo log会指向老的undo log (undo no=0) .
假设现在执行:
UPDATE user SET id=2 WHERE id=1;
对于更新主键的操作,会先把原来的数据deletemark标识打开,这时并没有真正的删除数据,真正的删除会交给清理线程去判断,然后在后面插入一条新的数据,新的数据也会产生undo log,并且undo log的序号会递增
可以发现每次对数据的变更都会产生一个undo log,当一条记录被变更多次时,那么就会产生多条undo log,undo log记录的是变更前的日志,并且每个undo log的序号是递增的,那么当要回滚的时候,按照序号依次向前推,就可以找到原始数据
3. undo log是如何回滚的
以上面的例子来说,假设执行rollback,那么对应的流程应该是这样:
- 通过undo no=3的日志把id=2的数据删除
- 通过undo no=2的日志把id=1的数据的deletemark还原成0
- 通过undo no=1的日志把id=1的数据的name还原成Tom
- 通过undo no=0的日志把id=1的数据删除
4. undo log的删除
针对于insert undo log
因为insert操作的记录,只对事务本身可见,对其他事务不可见。故该undo log可以在事务提交后直接删
除,不需要进行purge操作。
针对于update undo log
该undo log可能需要提供MVCC机制,因此不能在事务提交时就进行删除。提交时放入undo log链表,等待purge线程进行最后的删除。
补充:
purge线程两个主要作用是:清理undo页和清除page里面带有Delete_Bit标识的数据行。在InnoDB中,事务中的Delete操作实际上并不是真正的删除掉数据行,而是一种Delete Mark操作,在记录上标识Delete_Bit,而不删除记录。是一种"假删除";只是做了个标记,真正的删除工作需要后台purge线程去完成
2.6 小结
undo log是逻辑日志,对事务回滚时,只是将数据库逻辑地恢复到原来的样子
redo log是物理日志,记录的是数据页的物理变化,undo log不是redo log的逆过程
最后
2022/8/11 15:44
p169~p172
Markdown 19091 字数 653 行数
HTML 16286 字数 341 段落