MySQL - 存储引擎之Innodb内存结构

InnoDB存储结构

根据架构图可以看出,Innodb主要分为内存结构与磁盘结构两部分

Innodb内存结构

Buffer Pool(缓冲池)

Buffer Poll 按照Page为存储单位进行存储,大小默认16KB,采用链表结构来管理Page(页),Page大概分为三种类型:

  • free page:没有被使用的page
  • clean page:被使用的page,但是数据没有被修改过(缓存数据与磁盘数据一致)
  • dirty page:被使用过的page(脏页,缓存中的数据和磁盘中的数据不一致)

针对上述三种类型,Innodb通过3种链表结构来维护管理:
1. Free List(空闲链表)

  • 作用:管理缓冲池中年未被使用的空闲页
  • 数据结构:双向链表(一个节点有两个指针域)
  • 工作流程
    1. 初始化时候,所有页加入Free List
    2. 需要读取新页时:
    • 从Free List头部获取空闲页
    • 加载磁盘数据到该页
    • 页从Free List移除
    1. 当页被释放时候,重新加入Free List尾部
  • 关键点
    • 缓冲池的空闲页"储备库"
    • 加载磁盘数据到该页
    • SHOW ENGINE INNODB STATUS;中的Buffer pool size包含Free List页数
    • 当Free List为空时触发页淘汰

2. Flush List(刷新链表)

  • 作用:管理需要写入磁盘的脏页(被修改的页)
  • 数据结构:按最早修改时间(oldest_modification)排序的双向链表
  • 工作流程
    1. 页首次被修改时,加入Flush List尾部
    2. 后台刷新线程:
    • 从Flush List头部获取最老的脏页
    • 异步写入磁盘
    • 写入成功后从链表移除
  • 关键点
    • 按LSN(Log Sequence Number)排序
    • 检查点机制基于Flush List工作
    • innodb_io_capacity控制刷新速率
    • SHOW STATUS LIKE 'Innodb_buffer_pool_pages_dirty'查看脏页数量

3. LRU List(最近最少使用链表)

  • 作用:管理已使用的内存页,实现页淘汰算法
  • 数据结构:改进的LRU双向链表(分New和Old区)
  • 工作流程
    1. 新页加载到Midpoint位置(Old区头部)
    2. 页被访问时:
    • 若在Old区且存活超过innodb_old_blocks_time,移至Young区头部
    • 在New区,移至链表头部
    1. 淘汰时从尾部移除Old区页
  • 关键优化
    • Midpoint Insertion:避免全表扫描污染缓存
    • Old Sublist:innodb_old_blocks_pct控制比例(默认37%)
    • reeze Period:innodb_old_blocks_time(默认1000ms)防止短期访问提升

普通LRU:末尾淘汰法,新数据从链表头部加入,释放空间时从末尾淘汰
改进LRU:链表分为New和Old两个部分,加入元素时不是从表头插入,而是从中间Midpoint位置插入(如果数据很快被访问,数据就向New头部移动,如果数据被访问很慢,就向Ol尾部移动等待淘汰)
主要解决:预读失效和Buffer Pool污染问题

链表整体协同工作流程图:
image
监控命令:

-- 查看链表状态
SHOW ENGINE INNODB STATUS\G

-- 查看页分配
SELECT 
  POOL_ID,
  FREE_BUFFERS AS `Free List`, 
  DATABASE_PAGES AS `LRU List`,
  OLD_DATABASE_PAGES AS `LRU Old区`,
  MODIFIED_DATABASE_PAGES AS `Flush List` 
FROM information_schema.INNODB_BUFFER_POOL_STATS;

重点参数介绍:

参数 默认值 作用
innodb_page_size 16384 page页大小(字节)
innodb_old_blocks_pct 37 Old区占LRU比例(%)
innodb_old_blocks_time 1000 Old区晋升等待时间(ms)
innodb_max_dirty_pages_pct 90 最大脏页比例(%)
innodb_io_capacity 200 每秒刷新页数上限
innodb_buffer_pool_chunk_size 134217728 每个实例的数据大小
innodb_buffer_pool_instances 1 Buffer Pool实例数
innodb_buffer_pool_size 134217728 总数据大小

Adaptive Hash Index(自适应哈希索引)

自适应哈希索引(AHI)是Innodb引擎内置的自动内存优化机制,通过监控查询模式,在内存中动态创建哈希索引来加速B+树查询
image
性能提升原理:

  1. O(1)访问速度:哈希索引 vs B+树的 O(log N)
  2. 减少B+树遍历:避免多级节点访问
  3. 降低CPU消耗:简化查询处理路径
  4. 自动优化:无需DBA手动干预

性能对比:

操作 B+树索引 AHI启用 提升幅度
等值查询 3-4次页访问 1次内存访问 5-8倍
高并发点查 大量树遍历 直接哈希定位 10倍+
热点数据访问 重复遍历路径 一次哈希命中 3-5倍

Change Buffer(写缓冲区)

Change Buffer是Innodb用于优化非唯一,二级索引写操作的组件,通过延迟写入操作来提升数据库性能
image
性能提升原理:

  1. 减少随机I/O:合并多个变更到单词磁盘写入
  2. 降低磁盘压力:避免即时写入索引页
  3. 提高相应速度:写操作无需等待磁盘I/O

性能对比:

场景 无Change Buffer 启用Change Buffer 提升幅度
批量INSERT 每次索引更新都需磁盘I/O 仅需1次合并写入 5-10倍
高并发UPDATE 大量随机写操作 批量顺序写入 3-8倍
DELETE操作 即时更新索引结构 延迟合并删除标记 2-5倍

工作原理:

  • 写入阶段
    image
  • 合并阶段
  1. 读取触发:当首次读取索引页时
  2. 后台合并:innodb_background_merge_threads线程定期处理
  3. 关闭数据库:系统关闭时强制合并
    image

配置参数:

参数 默认值 说明
innodb_change_buffer_max_size 25% Change Buffer最大内存占比
innodb_change_buffering all 缓冲操作类型
innodb_background_merge_threads 4 后台合并线程数

工作原理:

  • 创建机制
    image
  • 哈希结构
+---------------------+
| 哈希键               |
|(索引值 + 页号)       | => 指向缓冲池中的页
+---------------------+

配置参数:

参数 默认值 说明
innodb_adaptive_hash_index ON 是否启用AHI
innodb_adaptive_hash_index_parts 8 AHI分区数
innodb_adaptive_hash_index_threshold 100 触发创建阈值

Log Buffer(日志缓

Log Buffer是Innodb引擎的核心内存组件,用于临时存储重做日志(Redo Log)条目,作为磁盘日志文件与内存操作之间的高性能
image

性能提升原理:

  1. 批量写入:合并多次小I/O为单次大I/O
  2. 顺序写入优化:即使随机更新,日志仍顺序写入
  3. 异步提交:事务可先返回成功在持久化日志
  4. 减少磁盘压力:避免每次事务都直接写盘

工作流程:

  • 写入路径
    image

关键配置参数:

参数 默认值 说明
innodb_log_buffer_size 16MB 缓冲区大小
innodb_flush_log_at_trx_commit 1 刷盘策略
innodb_flush_log_at_timeout 1s 后台刷盘间隔

刷盘策略详解:

策略值 名称 持久性 性能 适用场景
1 每次提交刷盘 最高(ACID) 最低 金融交易系统
2 提交只写OS缓存 中等(OS崩溃可能丢数据) 常规业务系统
0 每秒刷盘 最低(崩溃丢1s数据) 最高 日志采集等
posted @ 2025-06-03 16:29  学弟Craze  阅读(41)  评论(0)    收藏  举报