23、生产环境:在生产环境中,如何基于机器配置来合理设置Buffer Pool?
1、生产环境中应该给Buffer Pool设置多少内存?
今天接着上一篇学习的Buffer Pool的一些内存划分的原理,来给大家最后总结一下,在生产环境中到底应该如何设置Buffer Pool的大小呢?
有的人可能会想,假设我有32GB内存,那么给Buffer Pool设置个30GB得了,这样的话,MySQL大量的CRUD操作都是基于内存来执行的,性能那是绝对高
但是这么想就打错特错了,你要知道,虽然你的机器有32GB的内存,但是你的操作系统内核就要用掉起码几个GB的内存
然后你的机器上可能还有别的东西在运行,是不是也要内存?然后你的数据库里除了Buffer Pool是不是还有别的内存数据结构,是不是也要内存?所以上面那种想法是绝对不可取的
如果你胡乱设置一个特别大的内存给Buffer,会导致你的MySQL启动失败的,他启动的时候发现操作系统的内存根本不够用了
所以通常来说,我们建议一个比较合理的、健康的比例,是给Buffer Pool设置你的机器内存的50%~60%左右
比如你有32GB的机器,那么给buffer设置个20GB的内存,剩下的留给os和其他人来用,这样比较合理一些。
假设你的机器是128GB内存,那么Buffer Pool可以设置80GB左右,大概就是这样的一个规则。
2、Buffer Pool总大小=(chunk大小 * Buffer Pool数量)的2倍数
接着确定了Buffer Pool的总大小之后,就得考虑一下设置多少个Buffer Pool,以及chunk的大小了
此时要记住,有一个很关键的公式就是:Buffer Pool总大小=(chunk大小 * Buffer Pool数量)的倍数
比如默认的chunk大小是128MB,那么此时如果你的机器的内存是32GB,你打算给Buffer Pool总大小在20GB左右,那么你得算一下,此时你的Buffer Pool的数量应该是多少个呢?
假设你的Buffer Pool的数量是16个,这是没问题的,那么此时chunk大小 * Buffer Pool的数量 = 16 * 128MB = 2048MB,然后Buffer Pool总大小如果是20GB,此时Buffer Pool总大小就是2048MB的10倍,这就符合规则了。
当然,此时你可以设置多一些Buffer Pool数量,比如设置32个Buffer Pool,那么此时Buffer Pool总大小(20GB)就是(chunk大小128MB * 32个Buffer Pool)的5倍,也是可以的。
那么此时你的Buffer Pool大小就是20GB,然后Buffer Pool数量是32个,每个Buffer Pool的大小是640MB,然后每个Buffer Pool包含5个128MB的chunk,算下来就是这么一个结果了
3、总结
我们再来做一点总结,就是说你的数据库在生产环境运行的时候,你必须根据机器的内存设置合理的Buffer Pool的大小,然后设置Buffer Pool的数量,这样的话,可以尽可能的保证你的数据库的高性能和高并发能力。
然后线上运行的时候,Buffer Pool是有多个的,每个Buffer Pool里多个chunk,但是公用一套链表数据结构,然后执行CRUD的时候,就会不停的加载磁盘上的数据页到缓存页里来,然后会查询和更新缓存页里的数据,同时维护一系列的链表结构。
然后后台线程定时根据LRU链表和flush链表,去把一批缓存页刷入磁盘释放掉这些缓存页,同时更新free链表。
如果执行CRUD的时候发现缓存页都满了,没法加载自己需要的数据页进缓存,此时就会把LRU链表冷数据区域的缓存页刷入磁盘,然后加载自己需要的数据页进来。
整个Buffer Pool的结构设计以及工作原理,就是上面我们总结的这套东西,大家只要理解了这个,首先你对MySQL执行CRUD的时候,是如何在内存里查询和更新数据的,你就彻底明白了。
接着我们后面继续探索undo log、redo log、事物机制、事务隔离、锁机制,这些东西,一点点就把MySQL他的数据更新、事物、锁这些原理,全部搞清楚了,同时中间再配合穿插一些生产经验、实战案例。
4、SHOW ENGINE INNODB STATUS
当你的数据库启动之后,你随时可以通过上述命令,去查看当前innodb里的一些具体去哪个看,执行 SHOW ENGINE INNODB STATUS就可以了。此时你可能会看到如下一系列的东西:
- w854
下面我们给大家解释一下这里的东西,主要讲解这里跟Buffer Pool相关的一些东西。
- Total memory allocated,指buffer pool最终的总大小是多少
- Buffer pool size,指buffer pool一共能容纳多少个缓存页
- Free buffers, 指free链表中一共有多少个空闲的缓存页是可以用的
- Datatbase pages和Old database pages,指LRU链表中一共有多少个缓存页,以及冷数据区域里的缓存页数量
- Modified db pages 指flush链表中的缓存页数量
- Pending reads 和Pending writes, 等待从磁盘上加载进缓存页的数量,还有就是即将从LRU链表中刷入磁盘的刷量、即将从flush链表中刷入磁盘的数量
- Pages made young和not young,指已经LRU冷数据区域里访问之后转移到热数据区域的缓存页的数量,以及在LRU冷数据区域里1s里被访问了没进入热数据区域的缓存页的数量
- youngs/s和not youngs/s,这就是说每秒从冷数据区域进入热数据区域的缓存页的数量,以及每秒在冷数据区域里被访问了但是不能进入热数据区域的缓存页的数量
- Pages read xxxx, created xxx,written xxx,xx reads/s, xx creates/s, 1xx writes/s, 指已经读取、创建和写入了多少个缓存页,以及每秒读取、创建和写入的缓存页数量
- Buffer pool hit rate xxx / 1000, 指每1000次访问,有多少次是直接命中了buffer pool里的缓存的
- young-making rate xxx / 1000 not xx / 1000 , 每1000次访问,有多少次访问让缓存页从冷数据区域移动到了热数据区域,以及没移动的缓存页的和苏亮
- LRU len指LRU链表里的缓存页的数量
- I/O sum指最近50s读取磁盘页的总数
- I/O cur指现在正在读取磁盘页的数量