来聊聊MySQL高性能背后的BufferPool

243 阅读3分钟

​本文已参与「新人创作礼」活动,一起开启掘金创作之路。

前言

MySQL数据库为适应如今高并发的场景,可以说做了诸多优化,其中,mysql的引擎,是有巨大改变的,今天的主题就是围绕着innodb这个引擎展开而讲的,高性能中的一小部分——引擎的缓冲区:bufferpool。常听说:MySQL数据库在较高配置的机器上每秒可以抗下几干的读写请求。 试想如果来一个请求就做一次以上的磁盘IO(随机IO),那是很难支撑高并发的。为了提速,根本上还是几个方面的问题:

  • 1、内存取代磁盘;
  • 2、随机IO变顺序IO。

        而用内存把随机IO处理为顺序IO就是BufferPool的任务之一。


Innodb引擎SQL执行流程

举个例子说明:下面是一张存在磁盘上的表数据,这张表叫web

+----+--------------+---------------------------+-------+---------+
| id | name         | url                       | alexa | country |
+----+--------------+---------------------------+-------+---------+
| 1  | Google       | https://www.google.cm/    | 1     | USA     |
| 2  | 淘宝          | https://www.taobao.com/   | 13    | CN      |
| 3  | 菜鸟教程      | http://www.runoob.com/    | 4689  | CN      |
| 4  | 微博          | http://weibo.com/         | 20    | CN      |
| 5  | Facebook     | https://www.facebook.com/ | 3     | USA     |
+----+--------------+---------------------------+-------+---------+

我想把其中一条数据修改一下

UPDATE web SET alexa='5000', country='USA' WHERE name='菜鸟教程';

那么!这条语句在mysql的innodb执行引擎中到底是怎样发生的?

  1. 磁盘文件(数据存储的地方)上的数据以一个page页的单位被读到bufferpool(内存)中。
  2. bufferpool先写undo日志,例如:把 ID=3,name=菜鸟教程,url=xxxx ,Alexa=4689,country=CN 这条数据 写入undo日志
  3. 执行器修改bufferpool里的记录。例如:bufferpool里数据更新为【ID=3,name=菜鸟教程,url=xxxx ,Alexa=4689,country=USA】
  4. 执行器修改记录记入redo log buffer。例如:【ID=3,name=菜鸟教程,url=xxxx ,Alexa=4689,country=USA】记入redo log buffer。
  5. redo log buffer 生成文件进磁盘。例如:【ID=3,name=菜鸟教程,url=xxxx ,Alexa=4689,country=USA】由内存到磁盘
  6. 执行器写binlog日志文件。例如:【ID=3,name=菜鸟教程,url=xxxx ,Alexa=4689,country=USA】记入binlog文件,以备日后事务回滚或者出现意外时用于恢复数据的。
  7. commit事务,记commit进binlog日志redo日志文件
  8. bufferpool里的记录记入磁盘文件

总结

乍一看,这不是增添了很多麻烦?这会变快吗?这不是会拖后腿吗?

MySQL每次更新语句都是更新的Buffer Pool里的数据。(更新内存快于更新磁盘)

记binlog日志、redo日志、undo日志保证恢复或回滚数据,且数据具有一致性。(mysql除了保证你的数据读写性能,还要保证数据安全,这步不能少,就看怎么优化会让这一步又省时又能完成任务)

Buffer Pool会顺序写磁盘文件。(mysql在内存里折腾一番,不仅仅是贪图内存快这点点小便宜,而是,折腾出顺序,让内存到磁盘这趟路走得更省时省力!)