MySQL5.7: 动态调整buffer pool size

简介:

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


相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
缓存 关系型数据库 MySQL
MySQL并发支撑底层Buffer Pool机制详解
【10月更文挑战第18天】在数据库系统中,磁盘IO操作是性能瓶颈之一。为了提高数据访问速度,减少磁盘IO,MySQL引入了缓存机制。其中,Buffer Pool是InnoDB存储引擎中用于缓存磁盘上的数据页和索引页的内存区域。通过缓存频繁访问的数据和索引,Buffer Pool能够显著提高数据库的读写性能。
563 2
|
9月前
|
存储 SQL 关系型数据库
mysql的undo log、redo log、bin log、buffer pool
MySQL的undo log、redo log、bin log和buffer pool是确保数据库高效、安全和可靠运行的关键组件。理解这些组件的工作原理和作用,对于优化数据库性能和保障数据安全具有重要意义。通过适当的配置和优化,可以显著提升MySQL的运行效率和数据可靠性。
218 16
|
9月前
|
存储 SQL 关系型数据库
mysql的undo log、redo log、bin log、buffer pool
MySQL的undo log、redo log、bin log和buffer pool是确保数据库高效、安全和可靠运行的关键组件。理解这些组件的工作原理和作用,对于优化数据库性能和保障数据安全具有重要意义。通过适当的配置和优化,可以显著提升MySQL的运行效率和数据可靠性。
190 4
|
10月前
|
缓存 关系型数据库 MySQL
图解MySQL【日志】——Buffer Pool
Buffer Pool 是数据库管理系统(DBMS)中用于缓存磁盘数据页的内存区域,主要包含数据页、索引页、undo 页等。它通过减少磁盘 I/O 提升性能,特别是在处理大型数据库时效果显著。查询时,整个数据页而非单条记录会被加载到 Buffer Pool 中,以提高访问效率。
201 0
图解MySQL【日志】——Buffer Pool
|
10月前
|
存储 缓存 关系型数据库
MySQL进阶突击系列(08)年少不知BufferPool核心原理 | 大哥送来三条大金链子LRU、Flush、Free
本文深入探讨了MySQL中InnoDB存储引擎的buffer pool机制,包括其内存管理、数据页加载与淘汰策略。Buffer pool作为高并发读写的缓存池,默认大小为128MB,通过free链表、flush链表和LRU链表管理数据页的存取与淘汰。其中,改进型LRU链表采用冷热分离设计,确保预读机制不会影响缓存公平性。文章还介绍了缓存数据页的刷盘机制及参数配置,帮助读者理解buffer pool的运行原理,优化MySQL性能。
|
SQL 关系型数据库 MySQL
MySQL 8.0报错--1118-Row size too large. The maximum row size for the used table type, not counting BLOBs,is 8126,
MySQL 8.0报错--1118-Row size too large. The maximum row size for the used table type, not counting BLOBs,is 8126,
1114 56
MySQL 8.0报错--1118-Row size too large. The maximum row size for the used table type, not counting BLOBs,is 8126,
|
存储 缓存 关系型数据库
深度解密 MySQL 的 Buffer Pool
深度解密 MySQL 的 Buffer Pool
263 0
|
SQL 缓存 关系型数据库
(十二)MySQL之内存篇:深入探寻数据库内存与Buffer Pool的奥妙!
MySQL是基于磁盘工作的,这句几乎刻在了每个后端程序员DNA里,但它真的对吗?其实答案并不能盖棺定论,你可以说MySQL是基于磁盘实现的,这点我十分认同,但要说MySQL是基于磁盘工作,这点我则抱否定的态度,至于为什么呢?这跟咱们本章的主角:Buffer Pool有关,Buffer Pool是什么?还记得咱们在《MySQL架构篇》中聊到的缓存和缓冲区么,其中所提到的写入缓冲区就位于Buffer Pool中。
1308 1
|
关系型数据库 MySQL 测试技术
MySQL 报错 ERROR 1709: Index column size too large
MySQL 报错 ERROR 1709: Index column size too large
657 4
|
缓存 关系型数据库 MySQL
MySQL Buffer Pool 解析:原理、组成及作用
MySQL Buffer Pool 解析:原理、组成及作用

推荐镜像

更多