MySQL日志(一)

MySQL日志(一)

在开始之前我们要弄清楚一件事,MySQL事务日志和MySQL日志文件的区别,首先MySQL事务日志是记录MySQL的执行引擎下完成的日志,而根据MySQL的架构又分为存储引擎层与Server层,因此下面说的是MySQL日志事务是在存储引擎层的操作日志,而所说的MySQL日志文件是MySQL Server层的日志,这点需要搞清楚。而本节主要是讲解一下MySQL的事务日志,其Server层日志文件在后续会有补充。

我们都知道,事务是MySQL的非常重要的特性,也是我们使用Innodb作为默认的存储引擎的重要依据之一。

然而,事务是怎么实现的呢,又是怎么存储到磁盘的呢?这就不得不说redo log和 undo log了,MySQL数据库的原子性、一致性、持久性都是通过redo log和undo log完成的。有人会问,那隔离性哪去了,这个后面会讲,这里先不做讨论了。

有的开发人员或许会认为undo是redo的逆过程,其实不然,redo和undo的作用都可以视为是一种恢复操作,redo恢复提交事务修改的也操作,而undo回滚记录到某个特定版本。因此两者记录的内容不同,redo通常是物理日志,记录的是页的物理修改操作。undo是逻辑日志,根据每行记录进行记录。

到这里我们就知道了,redo log主要负责事物的提交和写入,redo log主要负责事物回滚操作,这个涉及到mvcc版本号问题。接下来讲一下它们各自的基本概念吧。

redo log

InnoDB是事物的存储引擎,当事务提交时,必须先将持物的所有日志写入到重做日志文件进行持久化,等到事务commit操作完成才算完成。这里的日志是指重做日志,分为两部分组成,即redo Log和undo log。redo log用来保证事务的持久性,undo log用来帮助事务回滚以及MVCC的功能。redo log基本上是顺序写的,在数据库运行时不需要对redo log的文件进行读取操作,而undo log是需要进行随机读写的。

在《MySQL45讲》中,提到了一个例子,我觉得很适合来比喻redo log的作用。

在《孔乙己》这盘文章中,酒楼掌柜有一个专门记录客人赊账的粉板。
如果赊账的人不多,那么他可以把顾客名和账目写在板上。但如果赊账的人多了,粉板总会有记不下的时候,这个时候掌柜一定还有一个专门记录赊账的账本。

如果有人要赊账或者还账的话,掌柜一般有两种做法:

  • 一种做法是直接把账本翻出来,把这次赊的账加上去或者扣除掉;
  • 另一种做法是先在粉板上记下这次的账,等打烊以后再把账本翻出来核算。

当生意红火时,可能就没有那么多时间在账本上查找然后再修改,可能就先直接通过粉板进行记录。
同样的,Mysql也是如此,磁盘上的数据其实类似于账本,如果每一次更新操作都要进行寻址然后再随机写入,这个是十分耗费时间和性能的。

因此,MySQL也聪明的使用一种类似粉板的机制,其实就是 MySQL 里经常说到的 WAL(Write-Ahead Logging)技术。他的特点就是先写日志,在选择时间写入磁盘。这里的先写入日志也就是redo log了。

redo log一般在什么时候会刷入磁盘呢?

这里的刷入磁盘也就是常说的“落盘”,这里有一个可能会被容易误解的地方,redo log是以什么形式存储的呢?内存形式吗?如果这时候服务器突然断电了,那么在redo log这部分数据不就丢失了?MySQL事务还能遵循持久化的特性吗?

其实不然,MySQL的redo log其实也是会存储到磁盘的,但是为什么同样是写入磁盘,而落盘的操作却是低性能的?

这里的话就得说到MySQL在顺序写入和随机写入他的效率是不一致的,对redo log的写入磁盘是顺序写入的,其写入的性能十分的高。

好了,回到正题,redo log合适会落盘呢?其实想象一个场景,如果生意很火爆,掌柜很快发现写到粉板上的数据已经满了,无法再继续写入了,这时候是不是应该吧部分先写入账本,为新的记录腾出一部分空间呢?

与此类似,InnoDB 的 redo log 是固定大小的,比如可以配置为一组 4 个文件,每个文件的大小是 1GB,那么这块“粉板”总共就可以记录 4GB 的操作。从头开始写,写到末尾就又回到开头循环写
在这里插入图片描述
write pos 是当前记录的位置,一边写一边后移,写到第 3 号文件末尾后就回到 0 号文件开头。checkpoint 是当前要擦除的位置,也是往后推移并且循环的,擦除记录前要把记录更新到数据文件。

write pos 和 checkpoint 之间的是“粉板”上还空着的部分,可以用来记录新的操作。如果 write pos 追上 checkpoint,表示“粉板”满了,这时候不能再执行新的更新,得停下来先擦掉一些记录,把 checkpoint 推进一下。

有了 redo log,InnoDB 就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为crash-safe。

要理解 crash-safe 这个概念,可以想想我们前面赊账记录的例子。只要赊账记录记在了粉板上或写在了账本上,之后即使掌柜忘记了,比如突然停业几天,恢复生意后依然可以通过账本和粉板上的数据明确赊账账目。

undo log

也许有时候我们会有疑问,MySQL是怎么实现MVCC(多版本控制)和回滚的呢?
这里不得不提对的一种事务日志就是undo log,他是实现事务回滚的根本。

undo log和redo log记录物理日志不一样,它是逻辑日志。可以认为当delete一条记录时,undo log中会记录一条对应的insert记录,反之亦然,当update一条记录时,它记录一条对应相反的update记录。

当执行rollback时,就可以从undo log中的逻辑记录读取到相应的内容并进行回滚。有时候应用到行版本控制的时候,也是通过undo log来实现的:当读取的某一行被其他事务锁定时,它可以从undo log中分析出该行记录以前的数据是什么,从而提供该行版本信息,让用户实现非锁定一致性读取。

undo log是采用段(segment)的方式来记录的,每个undo操作在记录的时候占用一个undo log segment。

当然,undo log也会产生redo log,因为undo log也要实现持久性保护。

mysql的事务日志大概就是这样了,本文是基于个人对事务日志的理解,如有偏差与错误,欢迎指正与交流。
后续也会考虑写一篇mysql日志的文章和对redo log的change buffer做出详细的说明
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值