MySQLInnoDB存储引擎大观存储引擎大观
MySQL InnoDB 引擎现在广为使用,它提供了事务,行锁,日志等一系列特性,本文分析下 InnoDB的内部实现机
制,MySQL 版本为 5.7.24,操作系统为 Debian 9。MySQL InnoDB 的实现非常复杂,本文只是总结了一些皮毛,希望以后能
够研究的更加深入些。
1 InnoDB 架构
InnoDB 的架构分为两块:内存中的结构和磁盘上的结构。InnoDB 使用日志先行策略,将数据修改先在内存中完成,并且将
事务记录成重做日志(Redo Log),转换为顺序IO高效的提交事务。这里日志先行,说的是日志记录到数据库以后,对应的事
务就可以返回给用户,表示事务完成。但是实际上,这个数据可能还只在内存中修改完,并没有刷到磁盘上去。内存是易失
的,如果在数据落地前,机器挂了,那么这部分数据就丢失了。
InnoDB 通过 redo 日志来保证数据的一致性。如果保存所有的重做日志,显然可以在系统崩溃时根据日志重建数据。当然记
录所有的重做日志不太现实,所以 InnoDB 引入了检查点机制。即定期检查,保证检查点之前的日志都已经写到磁盘,则下次
恢复只需要从检查点开始。
2 InnoDB 内存中的结构
内存中的结构主要包括 Buffer Pool,Change Buffer、Adaptive Hash Index以及 Log Buffer 四部分。如果从内存上来
看,Change Buffer 和 Adaptive Hash Index 占用的内存都属于 Buffer Pool,Log Buffer占用的内存与 Buffer Pool独立。
Buffer Pool
缓冲池缓存的数据包括Page Cache、Change Buffer、Data Dictionary Cache等,通常 MySQL 服务器的 80% 的物理内存会
分配给 Buffer Pool。
基于效率考虑,InnoDB中数据管理的最小单位为页,默认每页大小为16KB,每页包含若干行数据。为了提高缓存管理效
率,InnoDB的缓存池通过一个页链表实现,很少访问的页会通过缓存池的 LRU 算法淘汰出去。InnoDB 的缓冲池页链表分为
两部分:New sublist(默认占5/8缓存池) 和 Old sublist(默认占3/8缓存池,可以通过 innodb_old_blocks_pct修改,默认值为
37),其中新读取的页会加入到 Old sublist的头部,而 Old sublist中的页如果被访问,则会移到 New sublist的头部。缓冲池的
使用情况可以通过 show engine innodb status 命令查看。其中一些主要信息如下:
Change Buffer
通常来说,InnoDB辅助索引不同于聚集索引的顺序插入,如果每次修改二级索引都直接写入磁盘,则会有大量频繁的随机