思考一个问题

为什么在你当update时,事物提交之前先不断的写redo log呢?

如果你看过白日梦前面介绍buffer pool的文章,这个问题的答案想必你也能很快的想出来:MySQL为了提高性能,你对它数据行的增、删、改操作其实都优先发生在内存(Buffer Pool)中。那你想,假如你update了某些数据,Buffer Pool中的数据页也就会被你改成脏数据页。那万一你刚修改完并提交了事物,还没来得及将数据落盘MYSQL就宕机了怎么办?

当MySQL重启的时候需要把方才修改的内容恢复出来吧,不然数据就不一致了。那怎么恢复呢?就借助redo log恢复。因为前面说了,当你begin事物开始操作时,会先写redo log,在操作数据页。这个数据恢复的过程也叫做重做。

checkponit机制

随着MySQL的运行,Buffer Pool中的数据页会被修改成脏数据页,当你开启事物进行一系列的操作时MySQL会为你不停的记录一堆日志,拿redolog来说,rodo log也是需要往先往内存中写,再以块的形式刷新回磁盘。

无论怎样都会存在这样一个中间过程:内存中存在脏数据页、和脏日志未来得及刷新回磁盘。

而本小节中要说的Checkpoint机制就是将这些脏数据刷新回磁盘的机制,即只要发生Checkpoint,就要将脏数据刷新回磁盘,反过来,当MySQL重启时会去找Checkpoint,并且根据Checkpoint的特性。MySQL可以明确的知道checkponit之前的脏数据已经落过盘了,重启时没必要进行重做。

看到这里你已经大概知道Checkpoint是什么了。我们在稍微总结一下Checkpoint机制的作用:

1、所谓的崩溃恢复,其实就是MySQL重启时照着redo log中的最后一次Checkpoint之后的日志回放一遍

2、因为Checkpoint会不断的更新,并且MySQL重启时只需要对Checkpoint之后的数据进行恢复,所以Checkpoint会缩短MySQL重启的时间。

3、因此每次进行Checkpoint时buffer pool中的脏数据页、redo log中的脏日志都会落盘。所以Checkpoint实际上起到了为这两者进行瘦身的作用。维持两个的可用性。

Checkpoint的种类及触发条件

有两种:Checkpoint

1、Sharp(急剧的) Checkpoint

触发时机:比如当MySQL关闭时,或者是切换要写的redo log时,会一次性将所有的脏日志全部刷新到磁盘中,这种模式下会对MySQL的性能带来较大的影响。

2、Fuzzy(模糊的) Checkpoint

这种模式下的Checkpoint每次仅将部分脏日志刷新到磁盘中

触发条件1:Master Thread Checkpoint

由master线程控制,每秒或每10秒刷入一定比例的脏页到磁盘。

触发条件2:FLUSH_LRU_LIST Checkpoint

从MySQL5.6开始可通过 innodb_page_cleaners 变量指定专门负责脏页刷盘的page cleaner线程的个数,该线程的目的是为了保证lru列表有可用的空闲页。

触发条件3:async/sync flush Checkpoint

同步刷盘还是异步刷盘。例如还有非常多的脏页没刷到磁盘,这时候会选择同步刷到磁盘,但这很少出现;如果脏页不是很多,可以选择异步刷到磁盘,如果脏页很少,可以暂时不刷脏页到磁盘

触发条件4:dirty page too much Checkpoint

脏页太多时强制触发检查点,目的是为了保证缓存有足够的空闲空间。too much的比例由变量 innodb_max_dirty_pages_pct 控制,MySQL 5.6默认的值为75,即当脏页占缓冲池的百分之75后,就强制刷一部分脏页到磁盘。

LSN

LSN全称是:log sequence number。

关于什么是LSN没什么难以理解的,它就是一个序列号。并且表空间中的数据页、缓存页、内存中的rodo log、磁盘中的redo log以及checkponit都有LSN标记。

LSN又啥用呢?比如MySQL重启时会对比数据页的LSN和redo log的LSN的大小,如果前者的LSN比后者小。说明数据页中缺失了一部分数据。如果满足其他数据恢复的条件,MySQL就会将LSN之后的这些redo 进行一次回方,完成数据的恢复。

举个需要重做的例子:假设你使用的是MySQL集群,从库通过binlog同步主库的数据。

理论上:你开启了事物,然后一顿操作然后提交事物。在你操作的过程中MySQL会为你记录undo log、redo log parpare、binlog、redo log commit。(两阶段提交)

然而不幸的是,当MySQL写完binlog、且未来得及写 redo log commit完成的事物最终的提交就挂了。

那MYSQL重启,由于未来得及commit,脏数据页没有刷新到磁盘上,所以重启时得到的数据时不准确的,但是,实际上MySQL会根据方才的redo log重做。因为binlog已经写完了,那就意味着从库已经完成了数据的同步。如果它不重做的话,它相对于从库就缺失了一部分数据,导致主从数据不一致。

关于这个例子,后面的文章中我还会非常详细的说。

当然关于LSN你还得了解:

在MySQL 5.6.3之前,LSN是一个4字节的无符号整数。当重做日志文件的大小限制从4GB增加到512GB时,由于需要额外的字节来存储额外的大小信息,因此LSN在MySQL 5.6.3中变成了8字节的无符号整数。

你可以执行如下SQL查看你的MySQL的LSN标记记录情况:

show engine innodb status\G

为了更彻底的理解LSN、checkpoint我们可以一起看下面几张图:

第一张:我去网上找讲LSN的帖子时发现的很多文章使用下面这张图

但是这张图的中我用方框圈出来的地方实际上搞错了。图中的LSN应该放在倒数第二条线上。

我参照上图模改一套版图、简述一下表达的意思如下:

前面说了表空间中的数据页、内存中的缓存页、内存中的redo log、磁盘中的redo log、checkpoint它们五者都有记录LSN。所以你可以看到,在12:00:00时刻,它们五者中的LSN都是100。

然后在12:00:00时刻你开启了一个事物,执行update语句,之前的文章说过,你的CRUD都优先发生在内存中,也就是buffer pool中。并且在修改内存中的数据前先记录redo log,所以buffer pool中的缓存页和内存中的redo log的LSN率先被更新成110。

紧接着你的事物中又执行了delete语句,同样的道理内存中的redo log和缓存页的LSN被更新为150。接着时间来到了12:00:01。触发了由参数innodb_flush_log_at_timeout(默认1s)redo log刷盘机制。redo log会部分落盘,所以上图中的磁盘上的redo log的lSN更新为150。

接着你的事物中又执行了一次delete语句。同理内存中的缓存页和内存中的redo log的LSN被更新成了300。

终于checkpoint机制触发了!checkpoint机制的触发意味着要将内存中所有脏数据落盘。因此内存中的缓存页磁盘成为磁盘上的数据页,也就是说磁盘上的数据页的LSN变成300。同理磁盘上的redo log的LSN变成300。checkpoint的LSN也更新成300。

然而你的事物并没有结束,你在12:00:02时刻又insert了一条数据,同上面的原因内存中的缓存页、内存中的redo log 的LSN被更新成800。

终于你的要提交事物了!默认情况下,根据上一篇文章中跟大家分享的双1配置。事物提交时,redo log会落盘,但是内存中的脏数据并不会落盘。所以磁盘上的redo log LSN被更新成800。也就是说此时除了表空间中的数据页的LSN、checkpoint的LSN其他的LSN均已达到最新的800。

直到最后checkpoint再次出现。这五者LSN重新保持一致。

来源:https://www.cnblogs.com/ZhuChangwu/p/14118951.html

mysql崩溃恢复过程_一起看下MySQL的崩溃恢复到底是怎么回事相关推荐

  1. mysql star item 失败_解决CentOS7下MySQL服务启动失败的问题.md

    --- title: 解决CentOs7下MySQL服务启动失败的问题 date: 2021-01-06 15:21:31 tags: MySQL --- 老夫前几天才在虚拟机的CentOS安装好My ...

  2. mac下mysql不支持中文_解决mac下mysql无法使用中文的问题

    MySQL.png 针对 mac 系统下 mysql 无法使用中文,在网上查找解决办法,大部分都是将 mysql 下的 default.cnf 复制到 /etc下并修改为 my.cnf 然后对文件进行 ...

  3. mysql连接字符串 端口_浅析C#下MySQL连接字符串数据库服务器端口号

    正常的C#下MySQL连接字符串配置,这是在MSSQL服务器端口是1433(默认)的情况下. 但是有时候,为了数据库服务器安全,这个端口会被改成其它的,这时再用这C#下MySQL连接字符串,连接数据库 ...

  4. mysql去掉秒杀场景_秒杀场景下mysql减库存逻辑优化

    [问题背景] 某天早上做活动,流量大量增长,导致大量更新库存操作失败. 操作mysql返回的错误均为"Lost Connection to mysql server",即mysql ...

  5. spring mysql中文乱码问题_解决Spring下MySQL出现乱码的问题

    花了我宝贵的3个小时才搞定,失败! 以前都是用Postgres,基本没有用过Mysql .怎么Postgres的时候从来没有这么麻烦啊,惆怅~~ 本来我的代码都是基于UTF-8的,用本机的Window ...

  6. mysql 条件查询分页_百万数据下mysql条件查询及分页查询的注意事项

    接上一节<百万数据mysql分页问题>,我们加上查询条件:select id from news where cate = 1 order by id desc limit 500000 ...

  7. mac mysql密码错误_解决mac 下mysql安装后root用户登录密码错误问题

    使用的mac OS 10.11  安装mysql后访问root/root用户失败,网上找了一些解决办法,下面记录下解决方法方便以后自己查询 概述(看懂下面就不用看了): 停服务:sudo /usr/l ...

  8. 查询电脑上mysql的密码忘记了怎么办_windows下mysql忘记root密码的解决方法 -电脑资料...

    方法一: 1.在DOS窗口下输入net stop mysql5 或 net stop mysql 2.开一个DOS窗口,这个需要切换到mysql的bin目录, 一般在bin目录里面创建一个批处理1.b ...

  9. mysql读写分离实现_脱离开发:Mysql读写分离方案之一

    案例:Mysql读写分离 技能目标: · 熟悉MySQL主从复制原理 · 熟悉MySQL读写分离原理 · 学会配置MySQL主从复制 · 学会配置MySQL读写分离 6.1 案例分析 6.1.1 案例 ...

最新文章

  1. 使用OpenCV加载TensorFlow2模型
  2. mysql取最接近的两个值_Mysql:获取一行中另一个字段的最高值和最...
  3. linux init进程是所有用户进程的祖先进程,Linux中init进程介绍及常用方法
  4. Java序列化闲聊:序列化和Json
  5. button 样式_实战PyQt5: 111-可以使用QSS样式表的部件
  6. uva 753(网络流最大流)
  7. H5与Native交互之JSBridge技术 1
  8. Focus 焦点定位
  9. idea中使用maven方式使用jetty+cmd中使用Jetty运行(maven)Web项目
  10. 使用Requests+xpath实现简单的数据爬取
  11. 于仕琪 老师新版本人脸识别 - DLL接口及Python语言案例
  12. 全面理解网络流中的最大流问题
  13. 松下PLC项目实例,两台CPU间通过RS485通讯,10轴定位控制
  14. java的8年来工作汇总
  15. Microsoft Windows PE
  16. python爬取boss直聘招聘信息_Python 爬取boss直聘招聘信息!
  17. 机器学习 scikit-learn GridSearchCV scoring 参数设置
  18. 计算机毕业学游戏设计师,学游戏设计有前途吗
  19. 无法勾选远程连接到计算机,客户端无法连接到远程计算机错误的解决方法
  20. c语言常用库函数使用要点,C语言常用库函数使用要点.doc

热门文章

  1. CloudCompare基础架构介绍(PPT)
  2. 在Ubuntu 16.04.3 LTS上搭建QUIC交互demo
  3. squid中的X-Cache和X-Cache-Lookup的意义
  4. memset初始化内存
  5. linux 使用sendmail发送邮件
  6. 《Linux命令行与shell脚本编程大全 第3版》Shell脚本编程基础---34
  7. 如何防止博客文章被窃取
  8. UITextField的详细使用
  9. live555学习笔记2-基础类
  10. Platform Builder 5下WinCE 5.0目录结构