几年了,作为一个码农终于把MySQL日记看懂了( 四 )


这句话怎么理解,看下面:
Redo log 与 ChangeBuffer(含磁盘持久化) 这2个机制,不同之处在于优化了整个变更流程的不同阶段 。
先不考虑Redo log、ChangeBuffer机制,简化抽象一个更新(insert、update、delete)流程:

  1. 从磁盘读取待变更的行所在的数据页,读入内存页中
  2. 对内存页中的行,执行变更操作
  3. 将变更后的数据页,写入至数据磁盘中
其中,流程中的步骤1涉及随机读磁盘IO;步骤3涉及随机写磁盘IO;刚好对应ChangeBuffer和Redo log 。
对那句话的理解答案:
  • ChangeBuffer机制,优化了步骤1——避免了随机读磁盘IO ,将不在内存中的数据页的操作写入ChangeBuffer中,而不是将数据页从磁盘读入内存页中
  • Redo log机制, 优化了步骤3——避免了随机写磁盘IO,将随机写磁盘,优化为了顺序写磁盘(写Redo log,确保crash-safe)
7.4 有没有用到ChangeBuffer对于Redo log的区别Redo log机制,为了保证crash-safe,一直都会用到 。有无用到ChangeBuffer机制,对于redo log这步的区别在于—— 用到了ChangeBuffer机制时,在Redo log中记录的本次变更,是记录new change buffer item相关的信息,而不是直接的记录物理页的变更(文章中第八节都有体现这一过程) 。在我们mysql innodb中, ChangeBuffer机制不是一直会被应用到,仅当待操作的数据页当前不在内存中,需要先读磁盘加载数据页时,ChangeBuffer才有用武之地 。
7.5 ChangeBuffer的merge过程
几年了,作为一个码农终于把MySQL日记看懂了

文章插图
 
除了访问这个数据也会触发 merge 外,系统有后台线程会定期 merge 。在数据库正常关闭(shutdown)的过程中,也会执行 merge 操作 。
merge过程做三步
  1. 从磁盘读入数据页到内存(老版本的数据页);
  2. 从 change buffer 里找出这个数据页的 change buffer 记录 (可能有多个),依次应用,得到新版数据页;
  3. 写 redo log 。这个 redo log 包含了数据的变更和 change buffer 的变更 。
八、日记大连贯U-R-B,一举攻破拿下前面分别讲的是Binlog、Undo log和Redo log,下面将他们都串联起来,在一些流程体现全部日记 。
同样,以一些最经典的更新语句例子展开说明 。
8.1 制造演示数据测试语句:插入语句+查询语句,a字段是普通索引
insert into ta(a,b) values(2,5),(7, 5)2、select * from t where a in (2, 7)假设原来的数据如下图,数据页page1在内存中,page2不在 。插入的数据(2,5)落在page1,数据(7,5)落在page2中 。
几年了,作为一个码农终于把MySQL日记看懂了

文章插图
 
8.2 假设没有日记和ChangeBuffer 示范先不考虑所有日记及ChangeBuffer机制,简化抽象一个更新insert流程
  1. 从磁盘读取待变更的行所在的数据页,读入内存页中
  2. 对内存页中的行,执行变更操作
  3. 将变更后的数据页,写入至数据磁盘中

几年了,作为一个码农终于把MySQL日记看懂了

文章插图
 
8.3 考虑所有日记和ChangeBuffer 示范--现有Innodb流程过程是 两阶段提交-----日记刷盘------数据刷盘(涉及Redo log lsn 和 ChangeBuffer的内容)
8.3.1 两阶段提交过程
  1. 数据(2,5)所在页page1在内存中直接更新内存;数据(7,5)所在页page2不在内存中,记录change buffer(具有唯一性的索引或者没有使用change buffer的操作是将磁盘中的数据页读入内存中并做更新) 。
  2. 写undo日记 。先写缓存,后面根据刷盘参数决定何时刷入磁盘,后面的redo/Binlog都一样 。日记刷盘 在每一个日记中基本已经提到,它和设置的参数有关,具体刷盘可以参考上文4.3和6.5章节,下文不会再展开介绍 。
  3. 写redo日记(先记在内存中的更新,然后记录在内存中的change buffer的改变)
  4. 日记状态改成prepare阶段 。
  5. 写Binlog日记 。
  6. 提交事务,日记状态改成commit阶段 。

几年了,作为一个码农终于把MySQL日记看懂了

文章插图
 
8.3.2 merge 过程紧接着上文,图片可上下参考,假设现在执行查询语句 “select * from t where a in (2, 7)” ,此次查询索引a=7所在的数据页不在内存中,并且上一步更新已经在change buffer中有记录,将会触发merge过程(参考第七章节7.5) 。
  1. 将page2读入内存
  2. 依次应用change buffer中的记录,得到最新版数据页
  3. 写入redo,之前记录的changebuffer改动,现在改成数据页的改动


    推荐阅读