MySQL5.7: 动态调整buffer pool size

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介:

在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,当然那样代码会复杂的很多很多。


相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
关系型数据库 MySQL 数据库
MySQL新增字段报错:ERROR 1118 -- Row size too large. The maximum row size for the used table type
MySQL新增字段报错:ERROR 1118 -- Row size too large. The maximum row size for the used table type
1467 0
|
SQL 关系型数据库 MySQL
|
SQL 存储 JSON
MySQL执行请求报错 Error: Row size too large (>8126)
最近遇到一个业务问题,在执行一个大的业务查询时会抛出异常报错,所以今天就总结一下 MySQL执行请求报错 Row size too large (>8126) 报错的相关问题。
|
关系型数据库 MySQL 存储
mysql innodb 的 row size上限
mysql innodb 的 row size上限背景在项目使用中,出现了以下报错: Error Code: 1118 - Row size too large (> 8126).Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help.
1703 0
|
11天前
|
关系型数据库 MySQL 数据库
mysql卸载、下载、安装(window版本)
mysql卸载、下载、安装(window版本)
|
1月前
|
关系型数据库 MySQL 数据库连接
关于MySQL-ODBC的zip包安装方法
关于MySQL-ODBC的zip包安装方法
|
29天前
|
关系型数据库 MySQL 数据库
rds安装数据库客户端工具
安装阿里云RDS的数据库客户端涉及在本地安装对应类型(如MySQL、PostgreSQL)的客户端工具。对于MySQL,可选择MySQL Command-Line Client或图形化工具如Navicat,安装后输入RDS实例的连接参数进行连接。对于PostgreSQL,可以使用`psql`命令行工具或图形化客户端如PgAdmin。首先从阿里云控制台获取连接信息,然后按照官方文档安装客户端,最后配置客户端连接以确保遵循安全指引。
82 1
|
24天前
|
Ubuntu 关系型数据库 MySQL
Ubuntu 中apt 安装MySQL数据库
Ubuntu 中apt 安装MySQL数据库
66 0
|
3天前
|
关系型数据库 MySQL Linux
Linux联网安装MySQL Server
Linux联网安装MySQL Server
13 0