前言

不知道大家没有想过mysql是如何保证事务里的数据不丢失的?没错,就是通过redo log(下文简称redo)。

注意,绝对的数据不丢失是做不到的。我们所谈论的redo log,是针对事务而言。我们只要能保证事务中的数据不丢就行,说简单点就是:redo保证了事务的原子性和持久性。

简单解释下:

原子性:要么都做了,要么都没做。不要只做一半。比如两个人互相转账,不允许出现一个人转了,而另一个人没收到钱的情况。也就是两条update要么全部执行,要么都不执行。

持久性:数据写到磁盘了。当然这个说法不严谨,比如硬盘坏了呢?为了好理解,我就这样写了!

redo是什么?

首先明确,redo是InnoDB引擎特有的。记录着事务里对数据的修改

在mysql中,如果修改了数据,那么事务提交前,首先会被记录成redo日志写入磁盘,等到事务提交时,再把新数据写入磁盘(你以为真的是这样)。

这也就是经常说的WAL(Write-Ahead Logging)。

redo的好处

那么为什么需要redo呢?

1.保证数据的持久性。众所周知,数据是记录在磁盘上的,如果事务提交后mysql突然挂了(比如断电之类的),那么内存里的数据,是不是就丢失了?我们数据恢复时候,通过redo 就可以恢复回来。

解释:因为我们在事务提交前都已经把相关日志写入了磁盘,所以碰到意外当然可以恢复。如果写redo的时候断电了呢?大致上可以认为事务回滚了。不过没这么简单,到底是回滚还是提交,还牵扯到bin log。我们下文会讲到。

2.redo只是记录了对数据的修改,数据会比一页数据小得多。大大减少了IO频率。

解释:显而易见吧,一条redo再怎么也不会有16k那么大吧!

当然,写redo并不是一条条写的。因为一条redo日志并不是写入的最小单位,一般来说至少都是几条一起写。这是因为一条修改语句对B+树的修改,绝大多数情况下都不会是只产生一个修改点,比如你要插入一条数据,叶子节点容不下了,那么就可能页分裂,同时还会更新许多内节点的信息。所以这一系列对底层B+树的操作,都会以一组的形式去写入磁盘。

具体的写入过程下文会讲。现在只需要知道,一个事务会包含许多SQL,而一条SQL修改语句,会产生很多组redo就行了,而这一组(学名:Mini-Transaction)才是写入的最小单元。

好奇的你可能又会问:那这一组也没法保证写入的原子性啊,写一半断电了怎么办呢?

是的,写入永远没法保证原子性,所以只能在读取的时候保证了。在一组redo日志里,结尾会有一个标志符。解析redo日志的时候,读不到这个标志符的话,这一组就不解析了。不过这个Mini-Transaction并不是为了保证事务,我个人觉得是为了保证那颗B+树不会被搞坏了。

3.redo日志的写入是顺序IO。而修改磁盘的B+树是随机IO。

解释:redo就是往一块硬盘的某个相邻的区域写就完事了。如果要直接去修改B+树,很可能这些页并不相邻,寻址会很慢的。当然,固态硬盘的随机IO会好很多。

小白疑问:

内存里有什么数据?

答:

众所周知,InnoDB磁盘上的一页大小是16k。我们操作数据时,都是先将磁盘上的某一页读到内存中,这块内存就叫Buffer Pool。它是连续的内存空间。

这个Buffer Pool,会缓存一些热点数据、磁盘预读之类的数据。这样,操作数据时,就不用每次都去磁盘读取了。调节了CPU和硬盘的读写速度不一致的矛盾。

Buffer Pool中的数据被修改后,但又没有刷到磁盘的话(这里指的是那颗B+树),就叫做脏页。脏页不会立即刷新到磁盘中。

redo写入磁盘全流程

1.将上文提到的一组redo log写入redo log buffer(依然在内存中,依旧是为了调节CPU与磁盘写入速度的矛盾)。

2.redo log buffer写入page cache(操作系统里的页,操作系统会找个时间自动刷到磁盘。或者你调用fsync函数就能确保刷盘)。

3.page cache的数据刷到磁盘。

上述第2,3步是我们可以控制的,通过设置innodb_flush_log_at_trx_commit的值就可以控制,该变量可选值如下:(跟redis的差不多)

1:每次都要严格落盘。会调用fsync,保证了数据落盘,但是性能较差。

2:redo log buffer的数据写入page cache就行了。这个时候如果mysql挂了但是操作系统没挂,是可以等待后续落盘的。

0:不立即写入page cache。交给后台线程处理(1s一次,不仅写入page cache还会调用fsync)。这种情况太危险,但是性能最好。

怎么选就看你自己了,一般比较重要的库就设为“双一”(还有一个是binlog里的sync_binlog)。

至此redo 落盘了,从数据恢复上来讲,是可以安心了。

但是还有问题:磁盘上的redo file空间是有限的。写满了怎么办?

有人会觉得这种概率很小,其实不是的,redo log的空间重用是很正常的。那么何时才能重用呢?或者说,我们能重用哪些空间呢?

下面一一解答:

1.何时才能重用redo空间呢?

回忆redo log的作用:记录对数据的更改。那么只要Buffer Pool里的脏页也被写入磁盘了,这些磁盘上的redo log就没意义了,可以重用。

2.我们能重用哪些空间呢?

checkpoint告诉了我们答案。

checkpoint

我个人认为这是一个名词,而不是动词。

在MySQL8.0官方文档里对checkpoint的定义如下:

=============================================

checkpoint

As changes are made to data pages that are cached in the buffer pool, those changes are written to the data files sometime later, a process known as flushing. The checkpoint is a record of the latest changes (represented by an LSN value) that have been successfully written to the data files.

=============================================

我只翻译最后一段话:

checkpoint是redolog里最新的改变。

看起来有些不通顺,没关系,我加上自己的理解再翻译一次(个人理解哈,与其他资料都不太一样):

checkpoint是一个过程。当负责刷脏页的后台线程刷不动了(此时磁盘上的redo日志文件被写满了),就需要用户线程帮忙标记下,看看哪些redo日志可以被覆盖。

具体来说,redo文件里有一个偏移量(学名叫checkpoint_lsn),偏移量小于此值的redo日志可以被覆盖。当后台线程刷不动的时候,就意味着文件已经写到了上次checkpoint_lsn标记的地方。此时用户线程需要去写入日志文件里checkpoint_lsn的值。改完后后台线程就可以继续刷刷刷了。

总结:因为redo写满了,需要用户线程去写入chechpoint_lsn值的过程就是checkpoint

============================================

其实谈到checkpoint是离不开LSN(log sequence number)。

LSN这个值是干嘛的呢?其实就是记录redo在log buffer里的位置的。我们往log buffer里写入数据,比如写了10字节的数据,那么LSN = 8704+12(头大小)+10。我们12是头的大小,当然还有体和尾,大致是这么算的,就不展开了。总而言之,你往log buffer写了多少字节的日志,LSN大致就会增大多少。

Buffer Pool里的脏页们,是一个链表结构。第一次被修改的页,会以头插法的形式插入到表头,每个脏页都记录着第一次对该页修改的LSN和最后一次对该页修改的LSN(显然一个页有很多数据,可能会被修改多次的)。如果不是第一次被修改,只需要修改脏页最后一次被修改的LSN即可。

你可能会问。为什么脏页被移到链表上时,还需要记录最早和最新的LSN?

因为是头插法,尾部的是最被修改的脏页,假设叫A。那么A的最小LSN就可以作为一个分水岭,小于该值的redo 日志就可以被覆盖了。当然这个最小值也是往磁盘中写入的checkpoint值。

你又可能想问,那记录最大的LSN干嘛呢?

其实是恢复的时候有用。暂时不展开,有人看记得留言让我回来补充下。

redo什么时候写入磁盘

1.后台线程刷刷刷。

2.后台线程刷不动了(其实就是磁盘日志写满了),用户线程就会去写入checkpoint的值。使得部分redo文件可以被重写。

3.事务提交时。脏页可以不写,但是redo log在提交前必须写!

4.log bugger空间不足。

5.正常关闭服务器。

等等等等。。。

redo log与binlog

我们其实只讲了事务提交时的冰山一角。

因为mysql提交时,是采取了两段提交协议的:

1.redo log 处于prepare阶段,日志写入到磁盘。

2.写入binlog。

3.提交事务。

我们刚刚讲了那么多,其实都是描写第1步而已。其实如果只是以恢复日志来说的话,redo log完全可以胜任。

那么中间插个binlog干嘛呢?其实我不知道。连某客时间的丁某都支支吾吾,吾等实在悟不出来。暂时写这么多吧。

redo log详解相关推荐

  1. javascript教程:console.log 详解

    对应WEB程序员,console.log 可以说是神器,极大地方便了程序开发.程序猿:学习了,用Console写日志比alert方便多了. console.log(object[, object, . ...

  2. bin log,redo log以及undo log详解

    1 bin log 1.1 定义 bin log应该说是Mysql里最核心的日志,是MySQL数据库级别的文件,记录对MySQL数据库各种引擎下执行修改的所有操作(包括DDL和DML语句),不会记录s ...

  3. Mysql的undo log详解

    一.简介 redo log是事务持久性的保证,undo log是事务原子性的保证.在事务中更新数据的前置操作其实是要先写入一个undo log. 二.作用 1.用于数据的回滚.比如数据执行时候发生错误 ...

  4. Android之----Log详解(Log.v,Log.d,Log.i,Log.w,Log.e)

    Android Log是 android.util.Log 类 常用的方法有以下5个: Log.v () -- VERBOSE Log.d () -- DEBUG Log.i () -- INFO L ...

  5. tf.log()详解

    tf.log(y) 计算元素 y 的自然对数, y=ex 计算出x 返回一个张量,与 y 具有相同的类型. tensor = tf.constant([[1.0,2.0,3.0],[1.0,2.0,3 ...

  6. JS--Console.log()详解

    对于JavaScript程序的调试,相比于alert(),使用console.log()是一种更好的方式,原因在于:alert()函数会阻断JavaScript程序的执行,从而造成副作用:而conso ...

  7. git log 详解

    git log 可以让我们查看提交commit history,接下来我们来一起探索git log提供的参数. $ git log commit 0005d1e3f54b79fe4707fbccc44 ...

  8. console.log详解

    console.log方法用于在控制台输出信息.它可以接受一个或多个参数,将它们连接起来输出. console.log('Hello World') // Hello World console.lo ...

  9. db2diag.log 详解

    转载地址:http://freebile.blog.51cto.com/447744/773435 db2diag命令,是用来查看db2数据库运行日志信息的,实际上,db2运行日志是记录在db2dia ...

  10. 你所不知道的console.log()(console.log详解)

    console.log,作为一个前端开发者,想必每天都会用它来做分析调试,但这个简单函数背后你所不知道的一面,很多人未必使用过,有一些也是很方便使用的 基础 首先,简单科普这个函数的作用.前端开发者可 ...

最新文章

  1. iphone6 iphone6 plus 放大显示模式高分辨率模式问题
  2. GPS UTC与北京时间的转换函数
  3. 全网最详系列教程-nacos配置中心详解-NameSpace、Group、DataID
  4. 搭载华为HiCar 新宝骏跨界融合打造智能出行生态圈
  5. 用 bmon 实时查看网络流量
  6. 计算机专业英语课后答案北京理工大学,计算机专业英语
  7. 开务正式加入中国信通院数据库应用创新实验室
  8. 二进制编辑和进程监控工具
  9. 全志A33 Android4.4 RTL8723DS WIFI/BT驱动调试
  10. logogogo最新变种XP.exe的分析(Win32.Logogo)
  11. vue的Des加密解密
  12. 实验室信息管理系统(LIMS)软件大盘点
  13. 盘点那些年,被Oracle收购的公司
  14. 用python下载视频代码_python实现视频下载
  15. 调用notify方法
  16. 使用ZPL控制Zebra打印机
  17. 让mysql的自增id重新从1开始
  18. 29岁转行程序员,39岁成为总裁,宫崎英高的游戏成名之路!
  19. db2 10.5 数据库审计
  20. java 语言程序设计 李尊朝 第12章 Swing 组件

热门文章

  1. 《东周列国志》第十九回 擒傅瑕厉公复国 杀子颓惠王反正
  2. 计算机替换字体怎么操作,电脑怎么更换字体-电脑更换字体的方法 - 河东软件园...
  3. 【2020 ACM Fellow 华人学者】 Wei Wang 加州大学洛杉矶分校
  4. 软件工程的6个阶段以及成果精简版
  5. 电脑PPTP更换IP教程
  6. java 支付宝 验证签名失败,支付宝支付错误返回ILLEGAL_SIGN,签名验证错误
  7. IDEA SpringBoot引入外部jar并打包
  8. 计算机桌面来回闪烁,Windows10系统电脑屏幕一直闪烁的解决方案
  9. 基于SSH的房屋租赁系统的设计与实现
  10. 令人期待的大戏:千亿百度