MySQL5.7: 动态调整buffer pool size

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介:

在5.7.5中提供了一个新功能,能够动态的对buffer pool size进行调整。

对应的changelog entry:

InnoDB: The innodb_buffer_pool_size parameter is now dynamic, allowing you to resize the buffer pool without restarting the server. The resizing operation, which involves moving pages to a new location in memory, is performed chunks. Chunk size is configurable using the new innodb_buffer_pool_chunk_size configuration option. You can monitor resizing progress using the new Innodb_buffer_pool_resize_status status variable. For more information, see Resizing the InnoDB Buffer Pool Online.
See Resizing the InnoDB Buffer Pool Online for more information.

从功能来看,当前只支持总体bp size的调整,并不支持bp instance调整,因此实现会比较简单,表是根据space id模 bp instance来选择的,如果允许动态调整bp instance,还需要处理bp实例间的迁移。

另外在resize的过程中,buffer pool是不可用的,用户请求将会被堵塞住一会,这意味着还无法做到真正的ONLINE。不过幸好这种resize操作,通常都还算比较快,偷偷在半夜业务负载低的时候操作下就行了。。。

其大约实现思路为:

0.background

buffer pool新成员变量 (buf_pool_t)

volatile ulint  n_chunks number of buffer pool chunks
volatile ulint  n_chunks_new new number of buffer pool chunks
buf_chunk_t*    chunks_old old buffer pool chunks to be freed after resizing buffer pool
ulint           old_size previous pool size in pages
ulint           withdraw_target target length of withdraw block list, when withdrawing
UT_LIST_BASE_NODE_T(buf_page_t) withdraw; base node of the withdraw block list. It is only used during shrinking buffer pool size, not to reuse the blocks will be removed

新的全局变量

volatile bool   buf_pool_resizing true when resizing buffer pool is in the critical path
volatile bool   buf_pool_withdrawing true when withdrawing buffer pool pages might cause page relocation
volatile ulint  buf_withdraw_clock; the clock is incremented every time a pointer to a page may become obsolete;
if the withdrwa clock has not changed, the pointer is still valid in buffer
pool. if changed, the pointer might not be in buffer pool any more

1.发起请求

设置变量innodb_buffer_pool_size时,触发函数innodb_buffer_pool_size_update,在必要的检查后(例如避免重复发送请求,或者resize的太小),发送信号量srv_buf_resize_event.然后立刻返回
因此设置变量成功,不等于bp 的size已经调整好了,只是出发了 一个resize请求而已.

不过我们可以通过如下status变量来监控resize的过程,例如:
root@(none) 09:47:43>set global  innodb_buffer_pool_size = 42949672960; show status like ‘innodb_buffer_pool_resize_status';
Query OK, 0 rows affected (0.00 sec)
+———————————-+————————————+
| Variable_name                    | Value                              |
+———————————-+————————————+
| Innodb_buffer_pool_resize_status | Withdrawing blocks to be shrunken. |
+———————————-+————————————+
1 row in set (0.00 sec)

在新的逻辑里,所有的buffer pool内存被划分为chunk单位,每个chunk的大小默认为128M,这种方式给增加/减少bp size带来了极大的便利,使得实现更简单了。

2.执行请求

新的独立线程buf_resize_thread专门用于后台进行buffer pool的size调整,它会监听用户发出的请求事件srv_buf_resize_event

当收到resize请求后,会进行如下动作(函数buf_pool_resize)
a) 计算调整后,每个bp instance的内存大小
b)更新每个bp instance的相关变量:
buf_pool->curr_size = new_instance_size;

buf_pool->n_chunks_new = new_instance_size * UNIV_PAGE_SIZE
/ srv_buf_pool_chunk_unit;

其中srv_buf_pool_chunk_unit为只读变量,默认为,受参数innodb_buffer_pool_chunk_size控制。Resize都是以CHUNK为单位进行的。

c)禁止自适应hash
btr_search_disable()
清楚所有索引的index->search_info->ref_count,设置所有的block->index = NULL,以及清理btr_search_sys->hash_index

d)如果降低buffer pool size,则计算需要缩小的chunk数目并设置:
buf_pool->withdraw_target = withdraw_target; ——>需要缩小的block数
设置buf_pool_withdrawing为TRUE

e)当需要缩小bp size时,将withdraw_target 这么多的block转移到新的区域,需要首先搜集对应的page,到buf_pool->withdraw链表.
函数buf_pool_withdraw_blocks 的流程大概为:
(1)buf_buddy_condense_free(buf_pool);
合并所有空闲的buddy,主要是用于压缩表的.
(2)扫描buffer pool
…首先扫描free list,将需要withdraw的block(buf_block_will_withdrawn) 从free list上取出,加入到buf_pool->withdraw链表
…然后刷一次LRU LIST,以期望刷出更多的空闲Page (buf_flush_do_batch),flush LRU长度受限
…重新为withdraw区域的block/buddies分配到无需withdraw的block上.从LRU的第一个block开始

上述过程在buf_pool->withdraw长度达到buf_pool->withdraw_target时结束,是个循环重复的过程

f).完成搜集需要缩减的block加入到buf_pool->withdraw后,设置buf_pool_withdrawing为false;

注意在这之前还是允许并发负载的,但随后进入的区域是不允许用户进行任何buffer pool操作的。

g)设置buf_pool_resizing为true.
获取所有的buffer pool mutex, 即buffer pool page_hash的x lock.

h)进入增加/删除chunk阶段
…当缩小bp size时,删除多余的chunk.释放相应的资源,清空buf_pool->withdraw
…重新分配buf_pool->chunks
…如果增长bp size的话,初始化新的chunk(buf_chunk_init(buf_pool, chunk, unit)),分配新的内存区域,初始化新的block等..
…最后设置buf_pool->curr_size为新的size
i)重置每个bp instance的read_ahead_area 和curr_pool_size
j) 如果bp size的改动超过上次的一半或2倍,则重设page hash,和zip hash
调用函数buf_pool_resize_hash(buf_pool)

k)设置buf_pool_resizing为false,并释放所有的buffer pool锁, 释放老的chunk

l)如果bp size的改动超过上次的一半或2倍,则重置lock sys ,AHI及数据词典的大小
2648                 /* normalize lock_sys */
2649                 srv_lock_table_size = 5 * (srv_buf_pool_size / UNIV_PAGE_SIZE);
2650                 lock_sys_resize(srv_lock_table_size);
2651
2652                 /* normalize btr_search_sys */
2653                 btr_search_sys_resize(
2654                         buf_pool_get_curr_size() / sizeof(void*) / 64);
2655
2656                 /* normalize dict_sys */
2657                 dict_resize();

m)更新change buffer的大小并开启AHI
ibuf_max_size_update(srv_change_buffer_max_size);

当然过程远没这么简单,还涉及到大量相关的代码路径,感兴趣的可以看看以下的rev:

worklog:
http://dev.mysql.com/worklog/task/?id=6117

官方文档:
http://dev.mysql.com/doc/refman/5.7/en/innodb-buffer-pool-online-resize.html

http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/8479
http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/8383

总的来说,这个功能没有让人感到特别惊喜,如果bp instance也能调整了,才是真正的resize,当然那样代码会复杂的很多很多。


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
11月前
|
存储 SQL 关系型数据库
【MySQL异常】Row size too large (> 1982). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNA
【MySQL异常】Row size too large (> 1982). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNA
85 0
|
存储 缓存 关系型数据库
【MySQL进阶-08】深入理解innodb存储格式,双写机制,buffer pool底层结构和淘汰策略
【MySQL进阶-08】深入理解innodb存储格式,双写机制,buffer pool底层结构和淘汰策略
559 0
|
2月前
|
SQL 缓存 关系型数据库
(十二)MySQL之内存篇:深入探寻数据库内存与Buffer Pool的奥妙!
MySQL是基于磁盘工作的,这句几乎刻在了每个后端程序员DNA里,但它真的对吗?其实答案并不能盖棺定论,你可以说MySQL是基于磁盘实现的,这点我十分认同,但要说MySQL是基于磁盘工作,这点我则抱否定的态度,至于为什么呢?这跟咱们本章的主角:Buffer Pool有关,Buffer Pool是什么?还记得咱们在《MySQL架构篇》中聊到的缓存和缓冲区么,其中所提到的写入缓冲区就位于Buffer Pool中。
116 1
|
2月前
|
关系型数据库 MySQL 测试技术
MySQL 报错 ERROR 1709: Index column size too large
MySQL 报错 ERROR 1709: Index column size too large
163 4
|
3月前
|
缓存 关系型数据库 MySQL
MySQL Buffer Pool 解析:原理、组成及作用
MySQL Buffer Pool 解析:原理、组成及作用
|
3月前
|
缓存 关系型数据库 MySQL
MySQL数据库——InnoDB引擎-架构-内存结构(Buffer Pool、Change Buffer、Adaptive Hash Index、Log Buffer)
MySQL数据库——InnoDB引擎-架构-内存结构(Buffer Pool、Change Buffer、Adaptive Hash Index、Log Buffer)
86 3
|
4月前
|
缓存 关系型数据库 MySQL
MySQL高效运行的秘密:BufferPool缓存机制深度剖析!
MySQL高效运行的秘密:BufferPool缓存机制深度剖析!
140 0
MySQL高效运行的秘密:BufferPool缓存机制深度剖析!
|
存储 SQL 缓存
【MySQL】change buffer,buffer pool,redo log,bin log,undo log的作用
【MySQL】change buffer,buffer pool,redo log,bin log,undo log的作用
120 0
|
4月前
|
SQL 缓存 关系型数据库
MySQL(三)SQL优化、Buffer pool、Change buffer
MySQL(三)SQL优化、Buffer pool、Change buffer
59 0
|
4月前
|
关系型数据库 MySQL
mysql 5.5.62版本建表语句报错: Index column size too large. The maximum column size is 767 bytes
mysql 5.5.62版本建表语句报错: Index column size too large. The maximum column size is 767 bytes
122 0

热门文章

最新文章