3.innodb内存结构

MySQL内存

 

1.缓冲池

内存的作用就是存储临时数据,负责磁盘与CPU之间的数据交互。

在MySQL中,innnodb是基于磁盘存储的,由于CPU和磁盘之间的速度差别较大。

所以开辟内存,创建缓冲池,将数据暂存到缓冲池中,从而弥补CPU和磁盘之间的速度差别。

 

数据库实例在进行读取操作时,先将读取到的内容放在缓冲池(内存)中,然后之后再读到该内容时,判断该内容是否在内存(缓冲池)中,存在,直接从内存中读取,否则从磁盘中读取

数据库实例修改数据库时,先修改缓冲池中的数据,然后再以一定的频率刷新到磁盘上,刷新机制称为checkpoint,采用该机制是为了提高性能

一般来说,缓冲池越大,可缓冲的数据越多,数据库实例执行操作时速度越快

 

查看innodb缓冲池的大小

show variables like 'innodb_buffer_pool_size'\g

单位是字节

 

查看innodb缓冲池的个数

show variables like 'innodb_buffer_pool_instances'\g

当前innodb中,缓冲池个数为1

 

观察缓冲池的状态

select * from information_schema.innodb_buffer_pool_stats\G

其中Buffer pool size   8191的单位是页,一页16KB,换算为字节8192*16*1024=134217728,和之前的结果相同

 

innodb缓冲池的数据种类

 

2.LRU List, Free List,Flush List

 innodb主要通过LRU List管理缓冲池,LRU(latest recently used),最频繁使用的页数据放在LRU List前部,最少使用的页数据放在LRU List尾部,

当缓冲池不能存放新的页数据时,释放LRU List尾部的页数据。页的大小默认为16K

 

innodb对LRU算法进行了优化,对LRU List加入了midpoint,midpoint之前的列表为new,之后的为old,new列表中的页数据都是活跃的热点数据(就是频繁被访问使用)

新读取到的页数据不直接放在LRU List的尾部,而是放在LRU List中的midpoint位置,数据页从old列表转入new列表时,称为page made young

 

通过innodb_old_blocks_pct 查看midpoint

show variables like 'innodb_old_blocks_pct'\g

innodb_old_blocks_pct为37,表示将新读取到的页数据放在LRU List尾部的37%的位置,即63%的活跃数据

 

加入midpoint的原因

如果不加midpoint,直接将数据放入LRU List的最前面,会导致最常被使用的页数据从LRU List中被剔除,而新加入的页数据并不一定是热点数据,

当再次访问被剔除的数据时,需要从磁盘中读取,速度慢

 

除了加入midpoint,innodb还引入了innodb_old_blocks_time,表示当访问到midpoint处的页数据时,old列表中的页数据等多久会被移到new列表中

如果该值越大,那么new列表中的页数据被刷出可能性就越小,因为innodb_old_blocks_time导致数据页没有从old列表转移到new列表的,称为not page made young

 

查看innodb_old_blocks_time

show variables like 'innodb_old_blocks_time'\g

 

修改innodb_old_blocks_time

set global innodb_old_blocks_time=500;

当数据库刚启动时,LRU List为空, 所有的内存页都在Free List中,

当有访问数据的操作时,判断Free List是否有可用空页,有则从Free List将空页删除,放入LRU List中

否则淘汰LRU List末尾的页,将内存分配给新的页

 

查看 LRU List 和 Free List

show engine innodb status\G

database pages表示LRU List的页数

 

select * from information_schema.innodb_buffer_pool_stats\G

来查询缓冲池的内存分配情况

也能通过该语句查看 page made young和 not page made young的次数

 

innodb缓冲池的hit rate参数

可以通过

show engine innodb status\G

查看hit rate

这个值表示缓冲池是否正常运行,一般在95%以上

 

如果执行上述命令时,出现No buffer pool page gets since the last printout,表示没有缓冲池内存操作,可以执行一下下面的语句

select * from sys.session\G

然后再执行show engine innodb status\G,就能查看缓冲池的命中率了

 

innodb缓冲池的压缩页

innode缓冲池中的页的大小一般是16K,但是页可以压缩,压缩后的大小可以是8K 4K 2K 1K,这些压缩页由unzip_LRU来管理

根据压缩页大小不同,压缩页分别由不同的unzip_LRU来管理

 

unzip_LRU中的页通过伙伴算法分配,分配4K的页的过程如下:

1.检查4K的unzip_LRU中是否空闲页,有,则直接使用

2.若果没有,检查8K的unzip_LRU中是否空闲页,有,将8K的unzip_LRU中分成两个4K空闲页,存放到4K的unzip_LRU中

3.若没有,从LRU中申请16K的页,分为一个8K和两个4K的,病分别存入对应的unzip_LRU中

 

查看unzip_LRU

show engine innodb status\G

LRU列表中包含个页,没有压缩页,LRU的的页数包括unzip_LRU的页数

 

也可以通过下面的语句来查询

select * from information_schema.innodb_buffer_page_lru where compressed_size<>0;

查询结果为空,与show engine innodb status\G的结果一致

 

innodb缓冲池的脏页

当LRU中的页被修改后,成为脏页,脏页就是缓冲池中数据和磁盘数据不一致,数据库通过checkpoint机制将脏页写入磁盘

而脏页不仅存在LRU List中,也存在于Flush list中,Flush list中的页都是脏页,只不过Flush list负责将脏页写入磁盘,而LRU List负责管理缓冲池

 

查看脏页

select * from information_schema.innodb_buffer_page_lru where oldest_modification!=0;

可见,脏页数为0

 

3.重做日志缓冲和额外内存池

除了缓冲池,LRU list Free list Flush list之外,MySQL内存结构还包括重做日志缓冲和额外内存池

 

重做日志缓冲的作用就是存放重做日志数据,然后以一定的频率将重做日志数据写入重做日志文件

有三种操作会将重做日志数据写入重做日志文件

1.master thread 每秒执行该操作一次

2.事物提交时

3.当重做日志缓冲的剩余空间小于总空间的一半时,会自动执行该操作

 

查看重做日志缓存

show variables like 'innodb_log_buffer_size';

 

额外内存池记录了缓冲池相关信息,当缓冲池很大时,额外内存池也对应需要加大,不是很重要

 

参考

《MySQL技术内幕,innodb存储引擎》

 

欢迎大家评论交流,作者水平有限,如有错误,欢迎指出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值