MySQL的事务实现之——redolog与undolog

事务
事务是数据库区别于文件系统的重要特性之一。在文件系统中,如果正在写文件,此时操作系统突然崩溃,这个文件很有可能就损坏了。
数据库事务,在数据库操作提交时,可以确保要么所有的修改都已经被保存,要么所有的修改都不保存。
事务的特性:ACID,即原子性(atomicity)、一致性(consistency)、隔离性(isolation)、持久性(durability)。
前面的文章介绍了InnoDB存储引擎 的锁机制,正是用来保证事务之间的隔离性。而事务的原子性、一直性、持久性又是怎么实现的呢?答案就是本章将要介绍的知识——redolog和undolog

1、redolog
redo log 称为重做日志,用来保证事务的原子性与持久性。重做日志来实现事务的持久性,由两部分组成:一是内存中的重做日志缓冲(redo log buffer),容易丢失;二是重做日志文件(redo log file),是持久的。
事务持久性的实现是通过 force Log at Commit机制工作的,就是当我们执行事务提交(commit)操作时,必须先将所有操作写入到重做日志文件进行持久化,然后完成commit,才算操作成功。在InnoDB存储引擎中,重做日志由两部分组成,redo log 和undo log。其中,redo log 用来保证事务的持久性,undo log 用来帮助事务回滚 及多版本控制(MVCC) 的功能。
在MySQL数据库中还有一种二进制日志(binlog),它是用来数据恢复及主从复制的。看起来和本文要说的重做日志redo log类似,都是记录了对于数据库操作的日志。然后,二者却有着本质的区别。
(1)重做日志是InnoDB存储引擎层面产生的,而二进制日志是MySQL数据库的上层产生的,并不仅仅只针对InnoDB存储引擎,其他存储引擎下也会产生二进制日志。
(2)二者记录的内容不同,二进制日志是一种逻辑日志,记录的是对应的SQL语句。而InnoDB存储引擎层面的redo log 是物理格式日志,记录的是对每个页的修改。(磁盘数据页的修改记录)
(3)两种日志写入磁盘的时间点不同,二进制日志在事务提交完成后进行一次写入。而InnoDB存储引擎层面的重做日志是在事务进行时不断地被写入。(这也是,当我们操作数据时,突然断电,而能保证事务的原子性及持久性)。
数据的恢复
InnoDB存储引擎在启动时,不管上次数据库运行是否是正常关闭,都会尝试进行恢复操作。因为重做日志记录的是
物理日志因此恢复速度比逻辑日志(比如二进制日志),要快很多。
InnoDB存储引擎的重做日志是物理日志。因此其恢复速度较之二进制日志恢复速度快很多。如下,

create table yyy (a int,b int, primary key(a),key(b));

执行如下SQL

insert into yyy (a,b) values(1,3);

由于需要对聚集索引页与辅助索引页进行操作,其记录的重做日志大致为:

page(2,3), offset 32, value 1,3   //聚集索引页
page(2,4), offset 64, value 2     //辅助索引页

可以看到,重做日志记录的是页的物理修改操作。恢复时,只需对修改后的操作进行恢复。所以,重做日志是幂等性的(不管重复执行多少次,结果时一样的。什么是幂等性,不太清楚的同学可以去网上查一下。这里不做过多解释。),这里可以结合着二进制日志一起理解,有些人可能会认为,二进制文件也是幂等的,这显然是错误的,比如insert操作,在二进制文件中就不是幂等,二进制文件中记录的就是一条插入sql 语句,重复执行时,数据库可能会产生多条相同的的重复记录(这里说的是可能,如果插入语句没有唯一索引字段)

2、undolog
重做日志记录了数据库事务行为,可以很好地通过重做日志,对页进行恢复,即“重做”操作。但是事务有时候需要进行回滚操作,这时候就需要undo。因此在对数据库进行修改时,InnoDB存储引擎不但会产生重做日志redo,还会产生一定量的undo。这样如果用户执行事务语句时由于某种原因失败了,又或者用户用一条 ROLLBACK语句请求回滚,就可以利用undo信息将数据恢复到修改之前的状态。
与redolog的不同之处是,undolog是前面说的逻辑日志,用户通常有这样的误解,认为执行undo后,数据库会恢复到之前的样子——但是事实并非如此。而只是逻辑的恢复到原来的样子,但是数据结构和页的本身可能已经不同了。这句话怎么理解呢 ?
用户执行了insert 10w条数据,可能会导致表的空间变大,开辟新的数据页,此时需要回滚,执行undo,删除之前插入的10w条数据,但此时表增大的空间不会消失。这样做的目的是,在多用户并发系统中,可能会有成千上万个并发事务,数据库主要是任务是协调对数据记录的并发访问,当一个事务修改当前页中的几条记录,与此同时另一个事务也在对同一个页中的另外几条记录进行修改,此时就不能将一个页回滚到事务开始的样子,这样会影响其他事物正在进行的工作。
所以undolog,是一种逻辑日志。即,当执行一条insert语句,需要回滚时,InnoDB存储引擎的undo记录的是与之相反的delete操作,当执行一条update语句时,同样对应着一种与update相反的操作。
undo除了保证数据的回滚,还有一个重要的作用就是MVCC,多版本控制,InnoDB存储引擎解决幻读的采用的就是多版本控制,非锁定一致性读,就是通过undo实现的,当用户读取一行记录时,若该记录被其他事物占用,当前事务可以通过undo读取之前的行版本信息,以此实现非锁定读。
最后,很重要的一点,undo log 同样会产生redo log,也就是undo log的产生会伴随着redo log 产生,毕竟undo log 也需要持久化的保护。

总结:
本文是本人在学习Mysql InnoDB的日志模块时,觉得比较重要的部分,能帮助我们快速学习理解redo和undo log知识点,避免长篇大论,失去学习耐心,方便大家学习。

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值