MySQL事务日志简介

第14章 MySQL事务日志

事务有4种特性:原子性、一致性、隔离性和持久性。那么事务的四种特性到底是基于什么机制实现呢?

  • 事务的隔离性由 锁机制 实现。
  • 而事务的原子性、一致性和持久性由事务的redo日志和undo日志来保证。
    • REDO LOG 称为 重做日志 提供再写入操作,恢复提交事务修改的页操作,用来保证事务的持久性
    • UNDO LOG 称为 回滚日志 ,回滚行记录到某个特定版本,用来保证事务的原子性、一致性。
      UNDO 不是 REDO 的逆过程。REDO 和 UNDO都可以视为是一种 恢复操作
      内存中的修改会先写入redo日志记录,再进行修改,如果数据库中写入磁盘之前宕机了,数据库服务器重启后,会从redo日志中进行数据的恢复。
  • redo log: 是存储引擎层 (innodb) 生成的日志,记录的是"物理级别"(物理磁盘上的记录)上的页修改操作,比如页号xxx,偏移量yyy写入了’zzz’数据。主要为了保证数据的可靠性。
    • undo log: 是存储引擎层 (innodb) 生成的日志,记录的是 逻辑操作 日志,比如对某一行数据进行了INSERT语句操作,那么undo log就记录一条与之相反的DELETE操作。主要用于事务的回滚 (就执行undo日志中记录的所有逆操作,undo log 记录的是每个修改操作的逆操作) 和一致性非锁定读(undo log 回滚行记录到某种特定的版本——MVCC,即多版本并发控制)。

1. redo日志

InnoDB存储引擎是以页为单位来管理存储空间的。在真正访问页面之前,需要把在磁盘上的页缓存到内存中的Buffer Pool之后才可以访问。所有的变更都必须先更新缓冲池中的数据,然后缓冲池中的脏页会以一定的频率被刷入磁盘 (checkPoint机制),通过缓冲池来优化CPU和磁盘之间的鸿沟,这样就可以保证整体的性能不会下降太快。

1.1 为什么需要REDO日志

checkpoint机制可以保证数据写入磁盘,然而由于checkout机制是以一定的频率触发的不是每次变更都会触发,而是master线程隔一段时间去处理。有可能事务提交后,刚写入缓冲池,数据库宕机,这段数据就丢失无法恢复了(不能保证持久性)。
另一方面,事务包含 持久性 的特性,就是说对于一个已经提交的事务,在事务提交后即使系统发生了崩溃,这个事务对数据库中所做的更改也不能丢失。
为了确保持久性,将内存中执行的操作保存到物理磁盘上的一个文件中,这个日志文件就叫做redo日志。数据库如果发生了宕机,在内存中的修改由于已经记录到redo日志,此时只需要执行redo日志中的操作进行恢复操作写入磁盘(写入了之前提交的事务),保证了持久性
InnoDB引擎的事务采用了WAL技术 (Write-Ahead Logging),这种技术的思想就是先写日志,再写磁盘,只有日志写入成功,才算事务提交成功,这里的日志就是redo log。当发生宕机且数据未刷到磁盘的时候,可以通过redo log来恢复。
在这里插入图片描述

1.2 REDO日志的好处、特点

1. 好处
  • redo日志降低了刷盘频率
  • redo日志占用的空间非常小

存储表空间ID、页号、偏移量以及需要更新的值,所需的存储空间是很小的,刷盘快。

2 Redo日志的特点
  • redo日志是顺序写入磁盘的
    • 事务执行的过程中,每执行一条语句,就可能产生若干条redo日志,按顺序写入磁盘,即顺序IO,效率较高。
  • 事务执行过程中,redo log不断记录
    • redo log和bin log的区别,redo log是存储引擎层产生,bin log是数据库层产生;不断向redo log顺序记录日志,而bin log只有在事务提交时,才一次性写入bin log文件中。

2. undo日志

redo log是事务持久性的保证,undo log是事务原子性的保证。在事务中 更新数据前置操作 其实是要先写入一个 undo log

2.1 如何理解Undo日志

事务需要保证 原子性 ,也就是事务中的操作要么全部完成,要么什么也不做。但有时候事务执行到一半会出现一些情况,比如:

  • 情况一:事务执行过程中可能遇到各种错误,比如 服务器本身的错误操作系统错误 ,甚至是突然 断电 导致的错误。
  • 情况二:程序员可以在事务执行过程中手动输入 ROLLBACK 语句结束当前事务的执行。
    以上情况出现,我们需要把数据改回原先的样子,这个过程称之为 回滚 ,这样就可以造成一个假象:这个事务看起来什么都没做,所以符合 原子性 要求。
    在这里插入图片描述
    MySQL将为了回滚而记录这些内容称之为撤销日志回滚日志(即undo log)。查询操作不会修改任何用户记录,不需要记录查询操作的undo日志。
    此外,undo log 会产生 redo log,也就是说undo log需要持久性的保护。

2.2 undo日志的作用

  • 作用1:回滚数据
    • undo日志是逻辑日志,将所有的更改逻辑上的撤销,使得数据库恢复到以前的样子,但是数据结构和页本身与回滚之后可能有很大不同。
  • 作用2: MVCC
    • undo log的另一个作用是MVCC,即在InnoDB存储引擎中MVCC的实现是需要undo log参与的。当用户读取一行记录时,如果该记录被其他事务占用,当前事务可以通过undo log获取之前的行版本信息,以实现非锁定读取。

2.3 undo的存储结构(概要)

undo页的重用和undo log链

当我们开启一个事务需要写undo log的时候,就先去undo log segment中找到一个空闲的位置,当有空位时,就申请undo页,再到这个申请到的undo页中进行undo log的写入,一个页的默认大小是16K,会造成大量资源浪费。
于是undo页就被设计为可重用,数据提交时,不会立即删除undo页,undo log在commit之后,会被放入一个链表中,然后判断undo页的使用空间是否<3/4,如果如此,当前的undo页就可以被重用,其他的undo log记录在当前undo页的后面,因此undo log是离散的

2.4 undo的类型

在InnoDB存储引擎中,undo log分为:

  • insert undo log
    insert undo log是指insert操作中产生的undo log。因为insert操作的记录,只对事务本身可见,对其他事务不可见(这是事务隔离性的要求),故该undo log可以在事务提交后直接删除。不需要进行purge操作。
  • update undo log
    update undo log记录的是对delete和update操作产生的undo log。该undo log可能需要提供MVCC机制,因此不能在事务提交时就进行删除。提交时放入undo log链表,等待purge线程进行最后的删除。
2. 详细生成过程

在这里插入图片描述
对于InnoDB引擎来说,每个行记录除了记录本身的数据之外,还有几个因此的列:

  • row_id:如果没有为表显式地定义主键,并且表中也没有定义唯一索引,那么InnoDB会自动为表添加一个row_id的隐藏的列作为主键。
  • trx_id:每个事务会被分配一个事务id,当这个事务对某条记录变更之后,就会把这个事务的事务id写入这条记录的trx_id中。
  • roll_ptr:回滚指针,本质上就是指向undo log的指针。
    当我们执行INSERT时:
    插入的数据都会生成一条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的序号是递增的,那么当要回滚的时候,按照序号依次向前推,就可以找到我们的原始数据了。

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的逆过程。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值