《丁奇-MySQL45讲-09》之归纳总结

09 | 普通索引和唯一索引,应该怎么选择

  • InnoDB从磁盘读取的数据是以数据页为单位,在更新数据页时,首先去内存中查看是否有这个数据页,如果在内存中有,就直接更新内存中的数据;如果内存中没有这个数据页的话,InnoDB就会将这些更新操作缓存在change buffer中,这样就不需要从磁盘中读取这个数据页了。在下次查询需要访问这个数据页的时候,将数据页读入内存,然后执行change buffer中与这个页有关的操作,也就是执行merger操作,减少了磁盘的读写,提升了语句的执行速度。

  • change buffer什么时候写到磁盘上:

  1. 当操作系统空闲的时候后台会定期将这些change buffer写入到磁盘上。

  2. 系统关闭的时候。

  3. 还有一个虽然不是merger到磁盘上,但它是将数据页读到内存的时候会进行merger操作。

  • Innodb_change_buffering可以控制哪些DML操作使用change buffer,比如有inserts、deletes等,默认情况下是all。

  • Innodb_change_buffer_max_size控制占用缓冲区的百分比,默认情况下是25,最大值是50。

  • 对于唯一索引来说,所有的更新操作都必须判断唯一性,因此它必须将数据页从磁盘上读到内存上,数据页都已经读到内存了,就直接在内存中更新,没必要用到change buffer。而对于普通索引来说,直接更新change buffer就可以了,所以在更新操作的效率上普通索引更胜一筹,而两者的查询倒是没什么区别。

  • 写多读少使用change buffer可以加快执行速度(减少数据页磁盘IO),但是如果业务模型是写后立马会做查询,则会触发change buffer立即merge(个人理解是先将数据页行磁盘上读到内存中,然后change buffer在做merge过程)。这样的场景磁盘IO次数不会减少,反而会增加change buffer的维护代价。

  • 不知道很多人有没有跟我陷入第九篇文章讲解change buffer和redol log关系时陷入深深的懵懂,反反复复看了评论文章还是没懂,这里最关键的点是在第二篇文章中关于redo log的概念的理解,千万要记住redo log只负责记录数据页的变化,有了这个前提我们在来解释下这张图,如图所示:(摘抄自丁奇老师的图片

changer buffer - redo log

  1. 首先我们要明白的是change buffer本身记录的就是修改的操作,也就是脏页,也就是内存中的脏页,这部分脏页有可能已经被刷盘了(对应图中的ibdata1),也有可能还没有(完全就是机制的问题,不知道老师后续会不会将这块内容)

  2. 上面我们提到redo log会记录数据页的变化,既然change buffer和page1(红色部分)都是修改的部分,那么它两也都会记录到redo log中,至于什么时候写入到redo log中有很多争议,丁奇老师也没有明确指明,个人认为脏页写到内存后就可以写入redo log了,但有一个疑问,如果将磁盘上的数据页读到内存中,change buffer发生merge操作,那么此时还会在写redo log吗?(好多知识点,要吐了)看了第十篇大概也是会...此时写入的这部分应该算是数据页的修改(应用了change buffer)

  3. 对于page2的每次修改都会在change buffer中生成新的记录。

  • 思考题:change buffer一开始是在内存中,一旦断电后会不会丢失呢?
  1. 如果在断电前,change buffer就已经刷盘了,那重启就可以了。

  2. change buffer未刷盘,写入redo log处于未提交状态,查看bin log是否有对应的事务,没有的话就会回滚,则这部分数据丢失,有的话则会提交,最终可以在redo log中找到change buffer。

  3. change buffer未刷盘,redo log处于提交状态,直接从redo log恢复。

posted @ 2021-03-21 14:32  zliawk  阅读(52)  评论(0)    收藏  举报