浅析在线调整 innodb_buffer_pool_size
作者:zhou
mysql版本:5.7
先介绍一下 buffer pool:
在innodb存储引擎中数据访问以page为单位,page也是innodb管理数据库的最小磁盘单位,每个page的默认大小为16KB(可以通过参数innodb_page_size进行调整,在5.7增加了对32KB和64KB的大小支持,在此之前的版本支持4KB,8KB,16KB的大小设定),而buffer_pool是用来管理和缓存这些page的,innodb会把一块连续的内存划分给buffer_pool使用,并把buffer_pool等分为多个buffer_pool_instances(在上篇博客有介绍这个参数)。
buffer_pool是基于LRU算法来实现的,通过LRU算法来保证单独的一个page只会在一个buffer_pool_instances中,这样的划分模式可以提升buffer_pool的并发性能,每个单独的buffer_pool_instances其实都可以说是一个buffer_pool,innodb通过拉取page的方式将数据从文件中读取到buffer_pool里,并通过一个LRU list 来缓存这些page,经常访问的热点page放在在list的前面称之为list young区域,不经常访问的page 放在list的后面称之为list old区域,innodb访问数据时会先从buffer_pool中读取,没找到就会去访问数据文件进行查找,读取到page 并放到list old区域,当buffer_pool没有空闲的page时,会对list中old的page进行淘汰。
innodb 的LRU 算法简介:
innodb对原有的LRU算法进行了改进,LRU 算法的核心就是淘汰最久未使用的数据,在innoDB的实现上,按照5:3的比例把整个LRU list分成了 young 区域(前5/8)和 old 区域(后3/8),扫描的过程中新插入的page,都被先放到list old区域的头部区域,在间隔一秒以上再次访问到该page 就会移到 list young区域,这样的改进可以避免类似于全表扫描的操作对整个list造成过大的影响也保证了young区域的正常查询命中率。
LRU List:
介绍了buffer pool和改进后的innodb LRU算法,说说今天主要想介绍的动态调整innodb_buffer_pool_size WL#6117
,动态调整是5.7之后开始支持的,在5.7之前的修改需要重启实例这确实是在5.6包括之前的版本有点烦人的东西,比较重要的主库如果之前对buffer_pool没有一个足够大的设定,在线上重启还是有点限制的。
在线调整buffer_pool大小:
操作日志会输出在错误日志里
增加buffer_pool大小:
调整大小的操作由后台线程执行,增加buffer_pool 时:
1.申请适合的buffer_pool设定的值,然后关闭AHI。
2.遍历所有的buffer_pool,锁住buffer_pool,收集free list中的chunk page到withdraw,直到withdraw_target完成后释放buffer_pool的锁。
3.如果free list中没有收集到足够的chunk,则重复遍历收集,每次重复间隔时间会指数增加1s、2s、4s、8s…,以等待事务释放资源。
4.锁定buffer_pool,添加pages,调整hash table。
5.在lock_sys,自适应哈希索引,字典中调整了哈希表的大小,重新启用自适应哈希索引。
6.释放锁,打开AHI
7.调整完成
注意事项:
需要注意的是,在线调整buffer_pool的前提是当前负载不高,如果负载较高,是不建议直接进行调整的操作的,缓存设置的大起大落是有可能导致宕机的。
关于申请适合的buffer_pool设定的值的问题可以在我写的上篇
有提到有兴趣的同学可以去看一下。
我是zhou,如果需要转发请注明出处。