学习笔记
内存结构:
数据页、索引页、undo页、插入缓冲、自适应hash索引、Innodb存储锁信息、数据字典信息等。
Innodb是基于磁盘存储的,并将记录按照页的方式进行管理。
缓冲池就是一块内存区域,通过内存的速度来弥补直接操作磁盘速度较慢对数据库的影响。
对于数据库页的修改操作,首先会修改缓冲池中的页,然后以一定频率刷新到磁盘上,注意的是,并不是每次修改页都会触发刷新到磁盘上,而是通过一种checkpoint的机制刷新磁盘。
对于Innodb而言,其缓冲池的配置参数通过Innodb_buffer_pool_size设置。
mysql> show variables like '%innodb_buffer_pool_size%'\G;
*************************** 1. row ***************************
Variable_name: innodb_buffer_pool_size
Value: 134217728
1 row in set, 1 warning (0.01 sec)
ERROR:
No query specified
从Innodb 1.0.x 版本开始,允许有多个缓冲池实例。每个页根据hash平均分配到不同的缓冲池实例中,这样可以减少数据库内部资源竞争,增加数据库并发处理能力。可以通过参数innodb_buffer_pool_instances设置。
mysql> show variables like '%innodb_buffer_pool_instances%'\G;
*************************** 1. row ***************************
Variable_name: innodb_buffer_pool_instances
Value: 1
1 row in set, 1 warning (0.00 sec)
ERROR:
No query specified
数据库的缓冲池是通过LRU(Latest Recent used,最近最少使用)算法进行管理的。最频繁使用的页在LRU前端,最少使用的在LRU最后。当缓冲池不能存放新读取的页时,首先释放最尾端的。
缓冲池页的默认大小为16KB,Innodb中LRU加入了midpoint位置,新读取的页,会放到midpoint位置。默认在LRU列表的5/8处,midpoint之前的页称为new 列表,之后的页称为old 列表。midpoint位置可由参数Innodb_old_blocks_pct控制。
mysql> show variables like 'innodb_old_blocks_pct'\G;
*************************** 1. row ***************************
Variable_name: innodb_old_blocks_pct
Value: 37
1 row in set, 1 warning (0.00 sec)
ERROR:
No query specified
采用midpoint而不是直接将读取的页放在LRU的首部的原因是,避免将不活跃的数据刷出缓冲池,比如:一次全表查询,仅仅是这次查询使用而已,并不是真正活跃的页,如果放到首部可能会将真正活跃的页刷新出去。
为了解决这个问题,Innodb加入了新的参数innodb_old_blocks_time 来进一步管理LRU列表。当读取到mid位置时,需要过多长时间才能插入到LRU热端。这样可以尽可能的保证热点数据不被刷出。
mysql> show variables like 'innodb_old_blocks_time'\G;
*************************** 1. row ***************************
Variable_name: innodb_old_blocks_time
Value: 1000
1 row in set, 1 warning (0.00 sec)
ERROR:
No query specified
当数据库刚启动时,LRU列表是空的,这时页都存放在free列表中。当需要从缓冲池中分页时,首先需要判断free列表中是否有可用的空闲页,如果有就从free列表中删除,放入LRU列表中。否则根据计算,将LRU中末尾的页删除,将该内存空间分配给新的页。当LRU列表中的页从old 到 young 的过程叫做,page made young。由于innodb_old_blocks_time 参数,导致页没有从old 到 young的过程叫做page not made young。
Innodb 1.2版本开始,可以通过INNODB_BUFFER_POOL_STATS 表来查询缓存池状态
SELECT
POOL_ID,
POOL_SIZE,
FREE_BUFFERS,
DATABASE_PAGES,
HIT_RATE,
PAGES_MADE_YOUNG,
PAGES_NOT_MADE_YOUNG
FROM
information_schema.INNODB_BUFFER_POOL_STATS;
POOL_SIZE :共有多少个页/32768 * 8 页 , 32768*16K * 8 = 4G 缓存池大小
DATABASE_PAGES:LRU列表页数量
HIT_RATE:缓存池命中率,hit_rate/1000.如果不应该小于95%
Innodb存储引擎1.0.x 之后开始支持压缩页的功能,将原先的16K 压缩为 1K、2K、4K、8K。对于非16K的页 ,是通过unzip_LRU列表进行管理的
通过查询状态
> show engine innodb status\G;
LRU len: 31227, unzip_LRU len: 0
注意的是,LRU列表包含 unzip_lru 的页
Innodb 内存区内除了缓冲池,还有重做日志缓冲,首先将重做日志信息放到缓冲池中,然后通过一定的频率刷新到重做日志文件中。重做日志缓冲不需要太大,默认8M。
一下三种情况会将重做日志缓冲刷新到重做日志文件中。
额外的内存池用来对一些数据结构本身的内存进行分配,例如缓冲控制对象(buffer control block)记录的LRU,锁,等待等信息。额外的内存池不够时会从缓冲池中进行申请。因此,在申请了很大的InnoDB缓冲池时,额外的内存池也要适当的调大。通过参数innodb_additional_mem_pool_size来设置大小