做者:宋利兵html

来源:MySQL代码研究(mysqlcode)mysql

0、导读

本文重点介绍了InnoDB的checkpoint和Buffer Pool管理算法

04 – Checkpointsql

理论上来讲,若是MySQL数据库InnoDB存储引擎的buffer足够大,就不须要将数据自己持久化。将所有的redo log从新执行一遍就能够恢复全部的数据。可是随着时间的积累,Redo Log会变的很大很大。若是每次都从第一条记录开始恢复,恢复的过程就会很慢,从而没法被容忍。为了减小恢复的时间,就引入了Checkpoint机制。数据库

在了解checkpoint原理以前,先看两个名词:缓存

- 脏页(dirty page)

若是一个数据页在内存中修改了,可是尚未刷新到磁盘。这个数据页就称做脏页。并发

- 日志顺序号(Log Sequence Number)

LSN是日志空间中每条日志的结束点,用字节偏移量来表示。在Checkpoint和恢复时使用。异步

- Checkpoint 原理

假设在某个时间点,全部的脏页都被刷新到了磁盘上.这个时间点以前的全部Redo Log就不须要重作了。系统记录下这个时间点时redo log的结尾位置做为checkpoint. 在进行恢复时,从这个checkpoint的位置开始便可。Checkpoint点以前的日志也就再也不须要了,能够被清除掉。为了更好的利用日志空间,InnoDB并不会删除之前的Redo Log文件. InnoDB用几个Redo Log文件首尾相连,构建了一个环形缓存(circular buffer)的日志空间。函数

- 有了Checkpoint以后的Recovery性能

A. 首先要按期的将Checkpoint写入磁盘中某个地方.

B. 作Recovery时,从磁盘中读出Checkpoint.

C. 根据Checkpoint中的LSN找到Redo Log相应的位置,开始执行Redo Log.

- Sharp Checkpoint

对于繁忙的系统来讲,不多会出现这样的的一个时间点。为了能创造出这样一个时间点,最简单的办法就是:

A. 在某个时间开始中止一切更新操做

B. 全部的脏页被刷新到磁盘

C. 记录当前Redo Log的结尾位置到磁盘上.

D. Checkpoint结束,继续更新操做。

Sharp Checkpoint

这个方法称做Sharp Checkpoint,显然对于繁忙的系统, 这种方法是不合适的。能不能在checkpoint时不中止用户的操做呢?

- Fuzzy Checkpoint

如今咱们来看看,不中止更新操做的Checkpoint如何作:

A. 选取当前的Redo Log结束位置做为checkpoint点。

B. 将全部checkpoint点以前的脏页写入磁盘.

C. 将checkpoint点的位置持久化到磁盘上.

以下图所示,由于在刷脏页的同时用户还在更新数据,LSN1前的某个脏页在刷到持久存储以前就有可能会被LSN1以后的某个操做又给修改了。当刷脏页到磁盘时,LSN1后的部分操做(R1,R2对应的操做)就会被刷入磁盘。中止更新操做作checkpoint时(Sharp Checkpoint),持久存储中存储的数据是某个确切时间点的内存数据的快照。而不中止更新操做作checkpoint时,持久存储中存储的数据不是某个确切时间点的内存数据的快照。所以被称做Fuzzy Checkpoint.

Fuzzy Checkpoint

- 幂等(Idempotence)规则

如上图所示,checkpoint 在LSN1位置,当checkpoint完成时R1,R2对应的修改也被刷到了持久存储。恢复时要从LSN1位置开始,包括R1, R2在内。虽然,R1,R2的数据已经被刷入持久存储中了,R1,R2两个Redo记录仍然会被从新执。从新执行后,数据还能正确吗?

这就要求InnoDB的Redo Log要知足幂等规则。幂等规则要求不管redo log被重复执行了多少次,数据始终正确。

- 物理日志自然知足幂等规则

- 逻辑日志须要特殊处理才能支持幂等规则

前面说过InnoDB的Redo Log是物理到页,页内是逻辑日志。所以须要特殊处理,才能知足幂等规则。

- 数据页的最新(最大)LSN

为了知足幂等规则,InnoDB中每一个数据页上都记录有一个LSN。每次更新数据页时,将LSN修改成当前操做的redo log的LSN。在恢复时,若是数据页的LSN大于等于当前redo log的LSN,则跳过此日志。

- 异步Checkpoint

实现了幂等规则后,脏页就能够在任什么时候间,以任何顺序写入持久存储了。InnoDB的buffer pool有一套单独的机制来刷脏页。所以不少状况下checkpoint时,并不须要写脏页到存储。只是将全部脏页的最小的LSN记作checkpoint.这被称做“异步checkpoint"(不刷脏页到持久存储)

checkpoint的实如今log0log.c.

log_checkpoint()实现异步checkpoint.

- 同步Checkpoint

InnoDB的buffer pool经过LRU的算法来决定哪些脏页应该被写入持久存储。若是包含最小LSN的页面频繁的被更新,它就不会被刷到存储上。这样就可能致使checkpoint点很长一段时间没法前进,甚至致使日志空间被占满。这时就要按照LSN由小到大的顺序写一部分脏页到持久存储。这被称作"同步Checkpoint"(要刷脏页到持久存储).

log_checkpoint_margin().

log_calc_max_ages()用来计算,‘判断是否要执行同步checkpoint’用到的参数.

05 – 缓存池(Buffer Pool)

学习到这里,我更倾向于说这是一个”Redo+Undo+Buffer”的模式。为了提搞IO性能,脏页缓存在buffer中,Redo log也要先缓存在内存中,doublewrite也有内存buffer.

InnoDB实现了一套Buffer 机制,称做Buffer pool,将存储在文件中的数据以页为单位映射到内存中.

- Buffer Pool的页分类

Buffer pool内的页分为三种:

A. 未被使用的页(空白的buffer),没有映射到一个数据文件中页。

B. 净页,映射到了一个数据文件页,并且没有被修改过。内容和数据文件的页同样。

C. 脏页,映射到了一个数据文件页,而且数据被修改过。内容和数据文件的页不同。

- Buffer Pool的LRU页表

InnoDB维护了两个LRU链表。当空间不足时,用来决定哪些脏页应该被首先写入磁盘,哪些净页应该被释放掉。

A. buffer_pool->LRU,普通LRU链表,记录全部数据缓冲页。

B. buffer_pool->unzip_LRU,是压缩页(row_format=compressed)解压后数据缓冲页LRU链表。

LRU链表中的页面按最近一次的访问的时间顺序排列,头部是最近一次被访问的页面,尾部是最先一次被访问的页面。不管是读仍是写一个页面上的数据,都要先获取这个页面。所以能够在获取页面时,维护LRU链表.当获取一个页面后,将其放到LRU链表的头部便可。

buf_page_get_gen()和buf_page_get_zip()用来获取一个页面,他们调用

buf_unzip_LRU_add_block()和buf_page_set_accessed_make_young()来维护LRU链表。

- flush_list

同步checkpoint时,须要根据数据页修改的前后顺序来将脏页写入持久存储。所以除了LRU链表,buffer pool中还有一个按脏页修改前后顺序排列的链表,叫flush_list.当须要同步checkpoint时,根据flush_list中页的顺序刷数据到持久存储。

A. 一个页只在flush_list中出现1次,由于一个页面只须要写一次。

B. 按页面最先一次被修改的顺序排列。

06 – Mini-Transaction(MTR)

前面提到Redo Log将数据的操做细分到了页面级别。可是有些在多个页面上的操做是逻辑上不可分裂的。InnoDB中用Mini-Transaction来表示这些不可再细分的逻辑操做。

- MTR的一致性

为了知足MTR的一致性,MTR作了以下的设计:

A. MTR的全部日志被封装在一块儿,当MTR提交时一块儿写入redo log buffer.这样作有2个好处:

* 减小并发MTR对redo log buffer 的竞争。

* 连续的存储在一块儿,恢复时的处理过程更简单。

B. InnoDB在redo log的层面,将一个MTR中的全部日志做为Redo log的最小单元。在恢复时,一个MTR中的全部日志必须是完整的才能进行恢复。

- MTR日志的封装

为了在日志文件中区分不一样的MTR,MTR将MLOG_SINGLE_REC_FLAG或MLOG_MULTI_REC_END写入redo log(mtr_log_reserve_and_write()).

A. 若是MTR的日志中只有一行记录,在日志的开始处添加MLOG_SINGLE_REC_FLAG,表示MTR中只有一条记录。

B. 若是MTR的日志中有多行记录,在日志的结尾处添加一个类型为MLOG_MULTI_REC_END的日志,表明MTR的日志到此结束.

- MTR的LSN

A. 由于在将日志写入redo log buffer时,才能得到LSN。因此修改数据时,并无修改页上的LSN。须要在MTR得到LSN后统一修改。

B. 一个MTR只有一个LSN. 一个MTR内修改的全部页的LSN相同。这样checkpoint就不会出如今MTR的中间。

C. 在得到LSN后,若是被MTR修改的脏页不在buffer pool的flush_list里,就会被添加进去。看mtr_memo_slot_note_modification()和buf_flush_note_modification().

- 页级锁

MTR提交时才写日志到redo log的作法,决定了MTR要使用页级锁。

A. 一个页面不能同时被多个活动的MTR修改。

B. MTR中数据页的锁,直到MTR提交时(日志写入redo log buffer)后才释放。

锁对象存储在mtr的memo中。调用mtr_s_lock和mtr_x_lock来加锁时,锁对象被保存到memo中。解锁在mtr_memo_slot_release()中完成。

- MTR的ROLLBACK

看完MTR的代码发现mtr没有记录undo日志,也不能rollback. MTR都是很小的操做单元,并且每一个MTR都有明确的操做目标,所以比较容易保证其正确性。

A. 由于页面操做是在内存中完成,而且页面有固定的格式,所以不少的页面操做是不会失败的。InnoDB存储引擎中的不少写页面的函数都没有返回值.

B. 在对任何页面操做前,先要检查是否可能发生错误。若是可能发生错误就不能往下执行。如,当插入一行记录到B-Tree的节点时,首先检查页面有足够的空间。

C. 使用更大粒度的锁(如B-Tree的锁),而且按照必定的顺序加锁。这样才能不致使死锁问题。以上是本身看代码后的大概印象,不必定说到了正点上。MTR模块的代码虽简单,可是MTR在其余模块大量的使用。要透彻的理解MTR,估计还得要看其余模块的代码,整理出来大部分MTR操做过程才行.

06 – 参考

A. Database Systems: The Complete Book (2nd Edition)

B. Transaction Processing: Concepts and Techniques

C. how-innodb-performs-a-checkpoint

D. InnoDB fuzzy checkpoints

E. Heikki Tuuri Innodb answers – Part I

F. Heikki Tuuri Innodb answers – Part II

其余相关阅读

推荐订阅原文做者 宋利兵的公众号 MySQL代码研究

宋利兵 mysql_MySQL数据库InnoDB存储引擎Log漫游(3)相关推荐

  1. 1009MySQL数据库InnoDB存储引擎Log漫游

    00 – Undo Log Undo Log 是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中,还用Undo Log来实现多版本并发控制(简称:MVCC). - 事务的原子性(Atom ...

  2. mysql备份更换存储引擎_mysql数据库innodb存储引擎备份脚本

    mysql数据库innodb存储引擎备份脚本 #!/bin/bash # author: movekj # descript: backup mysql. full backup in sunday, ...

  3. MySQL数据库锁构建_MySQL数据库InnoDB存储引擎中的锁机制

    00 – 基本概念 当并发事务同时访问一个资源的时候,有可能导致数据不一致.因此需要一种致机制来将访问顺序化. 锁就是其中的一种机制.我们用商场的试衣间来做一个比喻.试衣间供许多消费者使用.因此可能有 ...

  4. MySQL数据库InnoDB存储引擎中的锁机制--转载

    原文地址:http://www.uml.org.cn/sjjm/201205302.asp 00 – 基本概念 当并发事务同时访问一个资源的时候,有可能导致数据不一致.因此需要一种致机制来将访问顺序化 ...

  5. mysql数据库永久设置手动提交事务(InnoDB存储引擎禁止autocommit默认开启)

    mysql数据库InnoDB存储引擎(默认情况下是自动控制提交事务)与其他关系型数据库在默认事务处理与其他关系型数据库略有不同,之前已经习惯Oracle数据库的手动提交事务的处理方式,mysql数据库 ...

  6. MySQL技术内幕-InnoDB存储引擎第2版-学习笔记-02

    MySQL技术内幕-InnoDB存储引擎第2版-学习笔记-02 6. 锁 ​ 人们认为行级锁总会增加开销.实际上,只有当实现本身会增加开销时,行级锁才会增加开销.InnoDB 存储引擎不需要锁升级,因 ...

  7. 前沿分享|阿里云数据库高级技术专家 宋利兵:阿里云企业级自治数据库RDS详解

    简介:本篇内容为2021云栖大会-企业级云原生数据库最佳实践论坛中,阿里云数据库高级技术专家 宋利兵关于"阿里云企业级自治数据库RDS详解"的分享. 本文将从2方面为大家介绍企业级 ...

  8. mysql 修改时间段内_详解mysql数据库MyISAM存储引擎如何转为Innodb及其中的注意点...

    概述 mysql数据库存储引擎为MyISAM的时候,在大访问量的情况下数据表有可能会出现被锁的情况,这就会导致用户连接网站时超时而返回502,此时就需要MySQL数据库MyISAM存储引擎转为Inno ...

  9. mysql数据库恢复数据_【技术分享】使用Innodb存储引擎的mysql数据库恢复

    作者:维一零 预估稿费:400RMB(不服你也来投稿啊!) 投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿 前言 某天,在测试一张新数据表的字段时,由于在phpmyadmin不断 ...

最新文章

  1. 获取checkbox所选中的值
  2. matlab 2009a使用教程,实验一 安装MATLAB R2009a软件及其简单操作
  3. SqlAlchemy个人学习笔记完整汇总
  4. 深入理解Java虚拟机——读书笔记01
  5. win7 安装c语言环境变量,win7下如何配置编程环境变量的方法
  6. ICCV 2019 | 基于关联语义注意力模型的图像修复
  7. 终于把CString转化为char*了
  8. Unity3D 旋转
  9. 内存管理-内存slub分配器(二)
  10. C/C++[codeup 2088]排名
  11. mysql regexp不支持_MySQL REGEXP正则表达式
  12. 基于c51的节日彩灯控制器的设计
  13. VMware 16 Pro安装MacOS Mojava 10.14
  14. IDEA-快捷键noob
  15. YOLOv4: Optimal Speed and Accuracy of Object Detection
  16. B树,B+树,树,二叉树,满二叉树,完全二叉树,二叉搜索树,平衡二叉树,
  17. Maven命令行参数
  18. 1097: C语言程序设计教程(第三版)课后习题10.4
  19. 在线检测你的密码是否被泄露
  20. CentOS 7使用samba共享文件夹

热门文章

  1. 12 个有效的提高编程技能的方法
  2. [译]介绍Spark2.4的用于处理复杂数据类型的新内置函数与高阶函数
  3. CSS垂直居中的11种实现方式
  4. ant使用ftp上传数据时配置的一个报错问题
  5. CodeBlocks调试功能(转)
  6. VMware SD-WAN 修复6个漏洞,可关闭整个企业网络
  7. 韩国遭 Lazarus Group 供应链攻击
  8. Promise面试题
  9. springcloud微服务系列之服务注册与发现组件Eureka
  10. 【C++】C++类和对象