目录
-
前期回顾
-
select 语句执行流程
-
update 流程
-
buffer_pool是如何维护的
1,前期回顾
上讲我们说到了mysql服务端的优化,还记得有有哪些么?
忘记的朋友回顾下MYSQl深入探索系列四 服务端优化
其中有个参数是调整buffer_pool缓存页总大小的
今天我们来细说下这个buffer_pool到底是个什么东西,怎么运行的,mysql又是如何维护它的。
2,select 语句执行流程
我们平时crud的时候大多场景是读取操作,即 select xxx from xx where xxx
那么你们知道mysql是如何运行这条sql的么?或者说mysql拿到这条语句后后台如何运行的么?
-
首先要经过mysql的解析器
-
然后再经过查询优化器sql会自动优化我们的sql找出一个最优的执行计划
-
调用sql执行器,执行器再去根据执行计划调用存储引擎。
-
存储引擎会从buffer_pool中查询,如果有就将结果返回,没有则从磁盘加载数据(会将相邻的几个数据页一起加载,即预读机制),然后放入到buffer_pool中,再将数据返回。
我们来画个图加深下理解:
这个图有点丑,大家谅解下,能看明白就行。
3,update 语句执行流程
那mysq 怎么执行更新操作呢?是删除buffer 在更新磁盘?还是同时写?
执行器将执行计划交给存储引擎以后,存储引擎会先更新buffer中的数据,然后写 undo log ,binlog ,最后事务提交时在写redo log 。
不直接更新磁盘?没错是的,mysql会在合适的时机去异步flush掉这些缓存脏页到磁盘上面。
我们还是画个图加深下理解:
4,buffer_pool是如何维护的
如果直接更新buffer,异步去flush dik 不知道大家有没有以下的疑问:
-
那如果此时并发很多的update 操作,那岂不是会有很多缓存脏页,mysql怎么直达先flush那个?
-
如果此时buffer_pool空间满了还是有查询过来怎么办?
-
哪些预读机制导致很多数据加载到buffer中并且始终没有被查询怎么办?
-
如果buffe有很多缓存页,mysql怎么知道用那个?随机用么?
我们带着这些疑问去看下,具体怎么维护这些缓存页的。
其实呀mysql是通过以下这3个东东搞定的free 链表 、flush 链表、lru链表。
先说free链表这个顾名思义,是空闲的缓存页的链表,当需要新的缓存页来存放数据的时候,会从free链表头部获取一个甚至多个缓存页来存放数据。
flush链表呢将是我们那些需要进行刷盘操作的缓存页。
但是如果free中没有了,此时flush中也都执行了flush操作,但是仍然不够存放,或者说此时还没释放这些脏的缓存页怎么办?这时候将要靠lru链表将最近最少访问的缓存页flush到disk上,那如何确定那个缓存页最近最少被访问呢?
我们每次执行查询的时候,如果buffer没有会从磁盘加载,然后存入buffer,这个时候会把该缓存页放入lru链表的头部,那链表尾部就是需要被淘汰,看似解决了问题,其实不一定哦,不要忘了mysql是有预读机制的,他会把相邻的数据一起加载进来,这样也会被放到lru头部。
聪明的msyql 通过冷热分离解决了这个问题,也就是说如果缓存也被命中读取了,就会被挪到lru链表的头部,这样可以保证尾部的都是冷数据,最近很少被使用的,这样将可以将它们淘汰掉,释放buffer空间。
总结
mysql在实际运行中其实free、flush、lru在不停的进行移动来维护buffer_pool,新的数据加载出来了,free中将去除掉该节点,lru中增加节点,跟新操作来了,lru中去除节点,flush中增加节点。
本次讲解的有点略浅,只是扫盲试的代大家过了一遍,如果有研究的,可以看下《mysql深入浅出》这本书。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
欢迎关注