MySQL: 20 生产经验:通过chunk来支持数据库运行期间的Buffer Pool动态调整
Posted 鮀城小帅
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL: 20 生产经验:通过chunk来支持数据库运行期间的Buffer Pool动态调整相关的知识,希望对你有一定的参考价值。
1. Buffer Pool不能在运行期间动态调整
Buffer Pool并不能在运行期间动态的调整大小。
因为想要动态调整Buffer Pool大小,比如Buffer Pool本来是8G,运行期间调整为16G。这一实现是需要向操作系统申请一块新的16GB的连续内存,然后把现在的Buffer Pool中的所有缓存页、描述数据块、各种链表,都拷贝到新的16GB的内存中去,这个过程是极为耗时的,性能很低下,是不可以接受的。
就目前所了解到的一整套原理,buffer pool 是绝对不能支持运行期间动态调整大小的。
2.基于chunk机制把buffer pool给拆小
mysql对上面的问题做了优化。设计了一个chunk机制,也就是说buffer pool 是由很多chunk组成的,它的大小是 innodb_buffer_pool_chunk_size参数控制的,默认值就是128MB。
案例:比如现在给Buffer Pool设置一个总大小是8GB,然后有4个buffer Pool,那么每个Buffer Pool就是2GB,此时每个buffer pool是由一系列的128MB的chunk组成的也就是说每个buffer pool会有16个chunk。
每个buffer pool里的每个chunk里就是一系列的描述数据块和缓存页,每个buffer pool里的多个chunk共享一套free、flush、lru这些链表。
如上图所示,每个buffer pool里已经有了多个chunk,每个chunk就是一系列的描述数据块和缓存页,这样的话,就把buffer pool按照chunk为单位,拆分为一系列的小数据块,但是每个buffer pool是共用一套free、flush、lru的链表的。
3.基于chunk机制在运行期间动态调整buffer pool大小
基于chunk机制实现的动态调整Buffer Pool原理如下:
假设现在Buffer Poool总大小是8GB,计划要动态加到16GB,那么此时只要申请一系列的128MB大小的chunk就可以了,只要每个chunk是连续的128MB内存就行了。然后把这些申请到的chunk内存分配给buffer pool就行了。
基于以上的chunk机制,就不需要额外申请16GB的连续内存空间,然后还要把已有的数据进行拷贝了。
4. 如何避免频繁清空缓存页
问题:如何避免执行crud的时候,频繁的发现缓存页都用完了,完了还得先把一个缓存页刷入磁盘腾出一个空闲缓存页,然后才能从磁盘读取一个自己需要的数据页到缓存页里来。
如果频繁这么搞,那么很多crud操作,每次都要执行两次磁盘IO,一次是缓存页刷入磁盘,一次是数据页从磁盘里读取出来,性能会降低的。
由于在使用缓存页的过程中,有一个后台线程会定时把LRU链表冷数据区域的一些缓存页刷入磁盘中。所以本质上缓存页一边被使用,一边会被后台线程定时的释放掉一批。
如果缓存页使用的很快,而后台线程释放缓存页的速度很慢,就必然导致发现缓存页被使用完了。
由于缓存页被使用的速度是无法控制的,是由Java系统访问数据库的并发程度来决定的,越是高并发访问数据库,缓存页必然使用的越快。而释放缓存页过于频繁,就会导致后台线程执行磁盘IO过于频繁,从而影响数据库的性能。
这里的关键在于,Buffer Pool的大小。
如果Buffer Pool足够大,也就是内存很大,空闲缓存页就会很多很多,即使空间缓存页会逐步的减少,但也是需要较长时间才会发现缓存页用完,然后才会出现一次curd操作执行的时候,先刷缓存页到磁盘,再读取数据页到缓存页来,这种情况是不会出现的太频繁的。
而一旦数据库访问高峰过去,缓存页被使用的速率下降了很多很多,然后后台线程会基于flush链表和lru链表不停的释放缓存页,此时空闲缓存页的数量会在数据库低峰的时候慢慢的增加了。
以上是关于MySQL: 20 生产经验:通过chunk来支持数据库运行期间的Buffer Pool动态调整的主要内容,如果未能解决你的问题,请参考以下文章
MySQL: 19 生产经验:如何通过多个Buffer Pool来优化数据库的并发性能
jQuery 支持 Transfer-Encoding:chunked