前言
redo log是事务持久性的保证,undo log是事务原子性的保证。在事务中 更新数据 的 前置操作 其实是要先写入一个 undo log 。
事务有四大特性: 原子性、一致性、隔离性和持久性。
- 事务的隔离性由 锁机制 实现。
-
而事务的原子性、一致性和持久性由事务的 redo 日志和undo 日志来保证。
REDO LOG
称为 重做日志 ,提供再写入操作,恢复提交事务修改的页操作,用来保证事务的持久性。- UNDO LOG 称为 回滚日志 ,回滚行记录到某个特定版本,用来保证事务的原子性、一致性。
有的DBA或许会认为 UNDO 是 REDO 的逆过程,其实不是。
- redo log是物理日志,记录的是数据页的物理变化,undo log不是redo log的逆过程
-
undo log是逻辑日志,对事务回滚时,只是将数据库逻辑地恢复到原来的样子。
-
redolog
:是存储引擎层(innodb
)生成的日志,记录的是”物理级别”上的页修改操作,比如页号xxx
、偏移量yyy
写入了'zzz”
数据。主要为了保证数据的可靠性; undo log
:是存储引擎层(innodb
)生成的日志,记录的是逻辑操作日志,比如对某一行数据进行了INSERT
语句操作,那么undolog
就记录一条与之相反的DELETE
操作。主要用于事务的回滚(undo log
记录的是每个修改操作的逆操作)和 一致性非锁定读(undo log
回滚行记录到某种特定的版本—MVCC
,即多版本并发控制)。
如何理解
事务需要保证 原子性 ,也就是事务中的操作要么全部完成,要么什么也不做。但有时候事务执行到一半会出现一些情况,比如:
- 情况一:事务执行过程中可能遇到各种错误,比如 服务器本身的错误 , 操作系统错误 ,甚至是突然 断电 导致的错误。
-
情况二:程序员可以在事务执行过程中手动输入 ROLLBACK 语句结束当前事务的执行。
以上情况出现,我们需要把数据回滚 ,造成一个假象:这个事务看起来什么都没做,所以符合 原子性 要求。
Undo log
作用
1.回滚数据
2.MVCC
1.存储结构
1.1回滚段 & undo 页
InnoDB对undo log的管理采用段的方式,也就是 回滚段(rollback segment) 。每个回滚段记录了1024 个 undo log segment
,而在每个undo log segment
段中进行 undo页 的申请。
在 InnoDB1.1版本之前 (不包括1.1版本),只有一个rollback segment
,因此支持同时在线的事务限制为 1024 。虽然对绝大多数的应用来说都已经够用。
从1.1版本开始InnoDB支持最大 128个rollback segment
,故其支持同时在线的事务限制提高到了 128*1024
mysql> show variables like 'innodb_undo_logs';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| innodb_undo_logs | 128 |
+------------------+-------+
1.2回滚段 & 事务
-
- 每个事务只会使用一个回滚段,一个回滚段在同一时刻可能会服务于多个事务。
-
- 当一个事务开始的时候,会制定一个回滚段,在事务进行的过程中,当数据被修改时,原始的数据会被复制到回滚段。
-
- 在回滚段中,事务会不断填充盘区,直到事务结束或所有的空间被用完。如果当前的盘区不够用,事务会在段中请求扩展下一个盘区,如果所有已分配的盘区都被用完,事务会覆盖最初的盘区或者在回滚段允许的情况下扩展新的盘区来使用。
-
- 回滚段存在于undo表空间中,在数据库中可以存在多个undo表空间,但同一时刻只能使用一个
undo
表空间。
- 回滚段存在于undo表空间中,在数据库中可以存在多个undo表空间,但同一时刻只能使用一个
-
- 当事务提交时,
InnoDB
存储引擎会做以下两件事情:
- 将
undo log
放入列表中,以供之后的purge操作 -
判断
undo log
所在的页是否可以重用,若可以分配给下个事务使用
- 当事务提交时,
1.3回滚段中数据分类
-
- 未提交的回滚数据(uncommitted undo information)
-
- 已经提交但未过期的回滚数据(committed undo information)
-
- 事务已经提交并过期的数据(expired undo information)
2.undo 类型
在InnoDB
存储引擎中,undo log
分为:
insert undo log
-
update undo log
3.undo log生命周期
3.1简要生成过程
3.1.1只有buffer pool时
3.1.2有了redo 和 undo
3.2详细生成过程
当insert时
begin;
INSERT INTO user (name) VALUES ("tom");
当update时
UPDATE user SET id=2 WHERE id=1
3.3undolog如何回滚
以上面的例子来说,假设执行rollback,那么对应的流程应该是这样:
1. 通过undo no=3的日志把id=2的数据删除
2. 通过undo no=2的日志把id=1的数据的deletemark还原成0
3. 通过undo no=1的日志把id=1的数据的name还原成Tom
4. 通过undo no=0的日志把id=1的数据删除
3.4undolog如何删除
- 针对于insert undo log
因为insert操作的记录,只对事务本身可见,对其他事务不可见。故该undo log可以在事务提交后直接删除,不需要进行purge操作。 -
针对于update undo log
该undo log可能需要提供MVCC机制,因此不能在事务提交时就进行删除。提交时放入undo log链表,等待purge线程进行最后的删除。
3.3小结
undo log是逻辑日志,对事务回滚时,只是将数据库逻辑地恢复到原来的样子。
redo log是物理日志,记录的是数据页的物理变化,undo log不是redo log的逆过程
参考文献
文章部分内容引用自宋红康老师的Mysql高级课程,在此表示感谢,如有侵权,请联系站长进行删除
<声明>:
谁都不是生下来就会的,都不是三体人,知识也可以遗传,我们的东西都是学习到的,所以每个人的知识体系难免有老师的身影,先学习后模仿,才能学会,至于笔记,摘抄部分我感觉难免,学会了就是自己的!