MySQL-InnoDB内存数据对象


作者:刘仁鹏
参考资料:《MySQL技术内幕:InnoDB存储引擎》


1.序言

  • InnoDB允许有多个缓冲池实例,每个页根据哈希值平均分配到不同的缓冲池实例中,以减少数据库内部的资源竞争,可以通过参数innodb_buffer_pool_instances来进行配置
  • 可通过SHOW ENGIN INNODB STATUS或INNODB_BUFFER_POOL_STATUS来观察缓冲的状态
SHOW ENGINE INNODB STATUS\G

SELECT POOL_ID, POOL_SIZE, FREE_BUFFERS, DATABASE_PAGES FROM INNODB_BUFFER_POOL_STATUS\G

图:InnoDB内存数据对象


MySQL-InnoDB内存数据对象_第1张图片
nnnn.png-94.8kB

2.具体实现

1.LRU List、Free List、Flush List

LRU列表

  • 数据库中的缓冲池是通过LRU(Latest Recent Used)算法来进行管理的。即:最频繁使用的页在LRU列表的前端,最少使用的页在LRU列表的尾端
  • 缓冲池中页的默认大小为16KB
  • InnoDB对传统LRU算法做了优化,加入了midpoint位置(midpoint insertion strategy)。即新读取到的页,并不直接放到LRU列表的首部,而是放到midpoint位置
  • 默认配置下,该位置在LRU列表长度的5/8处,midpoint位置可由参数innodb_old_blocks_pct控制
  • 这么做的目的是为了避免批量数据查询操作将LRU列表中的真实热点数据刷出
  • 为进一步解决批量操作刷出热点数据的问题,InnoDB还提供了innodb_old_blocks_time来表示页读取到mid位置后,需要等待多久才会被加入到LRU列表的热端。因此可在批量操作前将该值设大,操作完毕后再将该值设小。

Free列表

  • 当需要从缓冲池中分页时,会首先从Free列表中查找是否有可用的空闲页。如有,则将该页从Free列表中删除,放入LRU列表中。否则,淘汰LRU列表末尾的页,将该内存空间分配给新的页。
  • 观察方式:
SHOW ENGINE INNODB STATUS\G

SELECT POOL_ID, HIT_RATE, PAGES_MADE_YOUNG, PAGES_NOT_MADE_YOUNG FROM information_schema.INNODB_BUFFER_POOL_STATUS\G

SELECT TABLE_NAME, SPACE, PAGE_NUMBER, PAGE_TYPE FROM INNODB_BUFFER_PAGE_LRU WHERE SPACE = 1;
  • InnoDB支持压缩页的功能,将原本16KB的页压缩到1KB、2KB、4KB、8KB
  • 对于压缩页(非16KB的页),是通过unzip_LRU列表进行管理的。可通过SHOW ENGINE INNODB STATUS命令的unzip_LRU len查看。注意,unzip_LRU len是包含于LRU len的
  • unzip_LRU列表对不同大小的压缩页进行分别管理,通过伙伴算法分配内存

Flush列表

  • 在LRU列表中的页被修改后,称该页为脏页,即缓冲池中的页和磁盘上的页的数据产生了不一致,这时数据库会通过CHECKPOINT机制将脏页刷新回磁盘,而Flush列表中的页即为脏页列表
  • 注意:脏页既存在于LRU列表中,也存在在Flush列表中。LRU列表用来保证可用性,Flush列表用来保证一致性,二者互不影响
  • 通过元数据表INNODB_BUFFER_PAGE_LRU查看脏页时要加OLDEST_MODIFICATION > 0的查询条件

2.重做日志缓冲

  • InnoDB存储引擎首先将重做日志信息放到这个缓冲区,然后按一定频率刷新到重做日志文件
  • 重做日志缓冲大小默认为8M,可通过参数innodb_log_buffer_size控制。确保每秒产生的事务量在这个缓冲大小之内即可
  • 重做日志在以下三种情况下会将缓存刷到磁盘:
  1. Master每秒刷一次
  2. 每个事务提交时刷一次
  3. 重做日志缓冲剩余空间小于1/2时刷一次

3.额外的内存池

  • 在对一些数据结构本身的内存进行分配时,需要从额外的内存池中进行申请,当该区域内存不够时,会从缓冲池中申请
  • 例如:
  1. 每个缓冲池中的帧缓冲
  2. 对应的缓冲控制对象(这些对象记录了一些诸如LRU、锁、等待等信息)
  • 在申请了很大的InnoDB缓冲池时,也应考虑相应的增加额外内存池的大小

你可能感兴趣的:(MySQL-InnoDB内存数据对象)