RSS
菜单
全部文章快讯开发科技深度热点

第 7 章 InnoDB架构面试精讲

内容摘要

理解 InnoDB 架构是从"会写 SQL"到"懂数据库"的分水岭。本篇用 16 道高频题串起 InnoDB 的三大块——内存结构(Buffer Pool、Change Buffer、Log Buffer、AHI)、磁盘结构(表空间/段/区/页、doublewrite)、后台线程(page cleaner、purge、IO 线程),讲清 WAL、刷脏页、checkpoint 等运行机制。学完本篇,你能讲清"为什么内存命中率这么重要""为什么随机写性能不差""redo log 写满会怎样"。前置知识:第 3~6 章事务、锁、MVCC;本系列示例基于 MySQL 8.0。

📖 本篇简介:理解 InnoDB 架构是从"会写 SQL"到"懂数据库"的分水岭。本篇用 16 道高频题串起 InnoDB 的三大块——内存结构(Buffer Pool、Change Buffer、Log Buffer、AHI)、磁盘结构(表空间/段/区/页、doublewrite)、后台线程(page cleaner、purge、IO 线程),讲清 WAL、刷脏页、checkpoint 等运行机制。学完本篇,你能讲清"为什么内存命中率这么重要""为什么随机写性能不差""redo log 写满会怎样"。前置知识:第 3~6 章事务、锁、MVCC;本系列示例基于 MySQL 8.0。

目录

  • 1 InnoDB 架构高频考点地图
  • 题目 1InnoDB 整体架构分哪几块
  • 题目 2Buffer Pool 是干什么的怎么配大小
  • 题目 3Change Buffer 是什么解决什么问题
  • 题目 4Log Buffer 是干什么的
  • 题目 5Adaptive Hash Index 自适应哈希是什么
  • 题目 6InnoDB 磁盘结构表空间段区页是什么关系
  • 题目 7doublewrite 双写缓冲解决什么问题
  • 题目 8后台线程有哪些各自干什么
  • 题目 9脏页是什么时候怎么刷盘checkpoint 是什么
  • 题目 10WAL 预写日志是怎么回事
  • 题目 11redo log 写满会怎样
  • 题目 12InnoDB 页大小为什么是 16K
  • 题目 13怎么看 InnoDB 运行状态SHOW ENGINE INNODB STATUS
  • 题目 14Buffer Pool 命中率怎么算低了怎么办
  • 题目 15临出问题时 InnoDB 有哪些关键监控指标
  • 题目 16InnoDB 内存结构和磁盘结构怎么协同
  • InnoDB 架构速查表
  • 常见坑与注意事项
  • 复习清单
  • 练习题

1 InnoDB 架构高频考点地图

| 难度 | 典型问题 | 本篇对应 |

|---|---|---|

| 入门 | 整体架构?Buffer Pool? | 题目 1、2 |

| 基础 | Change Buffer?doublewrite? | 题目 3、7 |

| 进阶 | WAL?刷脏页?checkpoint? | 题目 9、10 |

| 实战 | 命中率?redo 写满? | 题目 11、14 |

一条主线记住:InnoDB 把数据缓存在 Buffer Pool,写先记 redo log(WAL),脏页异步刷盘;崩溃靠 redo 重放恢复。所有性能问题都围绕"内存命中率 + 刷盘速度"。

题目 1:InnoDB 整体架构分哪几块?

考点

  • 内存结构;
  • 磁盘结构;
  • 后台线程。

参考答案

InnoDB 架构分三块:

1. 内存结构:

  • Buffer Pool(数据/索引页缓存);
  • Change Buffer(二级索引写缓冲);
  • Log Buffer(redo log 缓冲);
  • Adaptive Hash Index(自适应哈希);

2. 磁盘结构:

  • 系统表空间(ibdata1)、独立表空间(*.ibd);
  • redo log(ib_logfile)、undo log 表空间、临时表空间;
  • doublewrite buffer;

3. 后台线程:master thread、IO 线程、page cleaner、purge thread。

  • 一句话:内存扛热数据,磁盘持久化,后台线程异步刷。
-- 查看内存结构大小(MySQL 8.0)
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';      -- 通常物理内存 50%~70%
SHOW VARIABLES LIKE 'innodb_log_buffer_size';       -- 默认 16M
SHOW VARIABLES LIKE 'innodb_change_buffer_max_size';

追问

  • 问:Buffer Pool 和 OS page cache 区别?答:Buffer Pool 是 InnoDB 自己管理的页缓存(带 LRU、脏页标记);OS page cache 是操作系统文件缓存,多了一层。
  • 问:为什么 InnoDB 不直接用 OS cache?答:自己管理能做预热、脏页刷新策略、压缩,比 OS cache 更懂数据库访问模式。

题目 2:Buffer Pool 是干什么的?怎么配大小?

考点

  • 数据页缓存;
  • 减少磁盘 IO;
  • 推荐内存 50%~70%。

参考答案

  • Buffer Pool:InnoDB 在内存中缓存数据页和索引页的区域,单位是页(16KB);
  • 读数据先查 Buffer Pool,命中就直接返回,未命中才从磁盘读页;
  • 写数据先改 Buffer Pool 里的页(标记为脏页),后台异步刷盘;
  • 配置:innodb_buffer_pool_size,专用数据库服务器建议物理内存的 50%~70%(留内存给 OS、连接、其他进程);
  • 8.0 支持多实例 Buffer Pool(innodb_buffer_pool_instances),减少并发锁竞争。
-- 查看 Buffer Pool 配置和状态
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
SHOW VARIABLES LIKE 'innodb_buffer_pool_instances';
-- 命中率:
SHOW STATUS LIKE 'Innodb_buffer_pool_read_requests';  -- 逻辑读
SHOW STATUS LIKE 'Innodb_buffer_pool_reads';         -- 物理读
-- 命中率 = 1 - reads / read_requests

追问

  • 问:Buffer Pool 满了怎么办?答:LRU 链表淘汰冷页;InnoDB 用改进的 LRU(midpoint insertion)防止全表扫描污染缓冲池。
  • 问: Buffer Pool 能热扩容吗?答:8.0 支持 SET GLOBAL innodb_buffer_pool_size=... 在线调整,不用重启。

题目 3:Change Buffer 是什么?解决什么问题?

考点

  • 二级索引写缓冲;
  • 减少随机 IO;
  • 8.0 改名 change buffer。

参考答案

  • Change Buffer:对非唯一二级索引的写操作(INSERT/UPDATE/DELETE),如果对应的索引页不在 Buffer Pool,不立即从磁盘读页,而是把修改记录到 Change Buffer;等以后这个索引页被读到内存时,再把修改 merge 进去;
  • 解决的问题:二级索引叶子是随机位置,写操作会导致大量随机读磁盘,性能差;Change Buffer 把这些写"攒"起来合并,把随机 IO 变顺序 IO;
  • 只对非唯一索引生效(唯一索引必须读页校验唯一性,不能延迟)。
-- 查看 Change Buffer 状态
SHOW ENGINE INNODB STATUS\G
-- INSERT BUFFER AND ADAPTIVE HASH INDEX 段
-- merged operations:合并次数
SHOW VARIABLES LIKE 'innodb_change_buffer_max_size';  -- 占 Buffer Pool 百分比

追问

  • 问:唯一索引用 Change Buffer 吗?答:不用,唯一索引要立刻校验重复,必须读页。
  • 问:Change Buffer 会不会丢数据?答:不会,它的修改也记 redo log,宕机后能恢复。

题目 4:Log Buffer 是干什么的?

考点

  • redo log 内存缓冲;
  • 批量刷盘;
  • innodb_flush_log_at_trx_commit。

参考答案

  • Log Buffer(redo log buffer):内存中待写 redo log 的缓冲区;
  • 事务提交时根据 innodb_flush_log_at_trx_commit 决定怎么刷盘:
  • =1:每次 commit 都 fsync 到磁盘,最安全;
  • =2:commit 写 OS cache,每秒 fsync;
  • =0:每秒刷盘(MySQL 崩丢 1 秒);
  • 默认 16MB,大事务/高并发写入可适当调大。
SHOW VARIABLES LIKE 'innodb_log_buffer_size';
SHOW VARIABLES LIKE 'innodb_flush_log_at_trx_commit';  -- 金融场景必须 1

追问

  • 问:Log Buffer 满了会怎样?答:自动刷盘到 redo log 文件,性能下降。
  • 问:为什么不直接每次写盘?答:fsync 很慢,批量写 + 组提交才能扛住高并发。

题目 5:Adaptive Hash Index 自适应哈希是什么?

考点

  • InnoDB 自动加的哈希索引;
  • 对频繁等值查询加速;
  • 用户不可控。

参考答案

  • AHI(Adaptive Hash Index):InnoDB 监控索引的查询模式,发现某个 B+ 树叶子被频繁等值访问,自动在其上建一层哈希索引;
  • 效果:等值查询从"沿 B+ 树走 3~4 层"变成 O(1) 哈希查找;
  • 对用户透明,不需要也不能手动建;
  • 8.0 默认开启 innodb_adaptive_hash_index=ON。
SHOW VARIABLES LIKE 'innodb_adaptive_hash_index';
SHOW ENGINE INNODB STATUS\G
-- INSERT BUFFER AND ADAPTIVE HASH INDEX 段看命中率

追问

  • 问:AHI 什么时候反而拖性能?答:热点极端、哈希桶冲突多时,内部 latch 竞争激烈,可关闭测试。
  • 问:为什么 InnoDB 不直接用哈希索引?答:哈希不支持范围查询和排序,B+ 树通用;AHI 只在热点等值上加,是补充。

题目 6:InnoDB 磁盘结构:表空间、段、区、页是什么关系?

考点

  • 从大到小:tablespace → segment → extent → page;
  • 页 16K;区 1MB(64 页);
  • 段 = 索引叶子段 + 非叶子段 + 回滚段。

参考答案

InnoDB 磁盘空间层次(从大到小):

| 层级 | 大小 | 说明 |

|---|---|---|

| 表空间 tablespace | 整个文件 | 独立表空间 *.ibd 或共享 ibdata1 |

| 段 segment | 多个区 | 数据段(叶子节点)+ 索引段(非叶子)+ 回滚段 |

| 区 extent | 1MB = 64 页 | 空间分配的最小单位 |

| 页 page | 16KB | 磁盘 IO 和 Buffer Pool 的最小单位 |

  • 一次磁盘 IO 读写一页(16KB);
  • 空间按区分配,避免碎片;
  • 8.0 默认每张表独立表空间(innodb_file_per_table=ON)。
SHOW VARIABLES LIKE 'innodb_page_size';          -- 16384 = 16K
SHOW VARIABLES LIKE 'innodb_file_per_table';    -- ON
-- 每张表对应一个 .ibd 文件

追问

  • 问:为什么不用更小的页?答:页太小扇出小、树高变高;16K 是权衡。
  • 问:独立表空间和共享表空间区别?答:独立表空间 per 表一个 .ibd,drop table 直接回收;共享 ibdata1 不会自动缩小,历史坑。

题目 7:doublewrite 双写缓冲解决什么问题?

考点

  • partial page write 半页写;
  • 先写 doublewrite 再写真实位置;
  • 恢复时用副本。

参考答案

  • 问题:InnoDB 页 16KB,OS 块 4KB。写页时如果写到一半宕机(断电),这个页就是损坏的(partial page write);
  • doublewrite:脏页刷盘时,先写到系统表空间的 doublewrite 区(连续 2MB),再写到真实位置;
  • 恢复时:如果真实页损坏,从 doublewrite 区复制一份完整页,再用 redo 重放;
  • 8.0 默认开启,性能损耗约 5%,换来数据安全。
SHOW VARIABLES LIKE 'innodb_doublewrite';   -- ON
-- 8.0.20+ 支持 atomic write(O_DIRECT + 原子写),可替代 doublewrite

追问

  • 问:为什么 redo log 不能直接修复半页写?答:redo 是"页某偏移改成某值",前提是页本身完好;页都坏了 redo 无从应用。
  • 问:ssd 还需要 doublewrite 吗?答:SSD 也可能半页写,仍然需要;支持原子写的 NVMe + O_DIRECT 可关。

题目 8:后台线程有哪些?各自干什么?

考点

  • master thread;
  • IO 线程;
  • page cleaner;
  • purge thread。

参考答案

| 线程 | 职责 |

|---|---|

| master thread | 全局调度,刷脏页、merge change buffer、undo 清理 |

| read/write IO thread | 处理异步 IO 请求(预读、写页) |

| page cleaner | 把 Buffer Pool 脏页刷到磁盘 |

| purge thread | 清理已提交事务的 undo log 和删除标记 |

| redo log flush thread | 把 log buffer 刷到 redo 文件 |

| monitor thread | 监控状态、打印错误日志 |

  • 这些线程都在后台跑,业务请求不直接等它们;
  • purge 线程和 MVCC 直接相关(见第 6 章)。

追问

  • 问:page cleaner 刷太猛会怎样?答:刷脏页占 IO 带宽,业务请求变慢,这就是"checkpoint 抖动"。
  • 问:purge 线程数能调吗?答:innodb_purge_threads,默认 4,大库可调大。

题目 9:脏页是什么时候、怎么刷盘?checkpoint 是什么?

考点

  • 脏页 = 内存页 ≠ 磁盘页;
  • 刷盘时机;
  • checkpoint 推进 redo 覆盖点。

参考答案

  • 脏页:Buffer Pool 里被修改过但还没写回磁盘的页;
  • 刷脏页时机:

1. Buffer Pool 空闲页不足,LRU 淘汰冷脏页;

2. redo log 写满,推进 checkpoint;

3. 系统空闲时 master thread 主动刷;

4. 正常关闭;

  • checkpoint:标记"这个点之前的脏页都已经落盘",redo log 只需要重放 checkpoint 之后的;
  • 刷脏页用双写(先 doublewrite 再真实位置),保证不半页写。
-- 查看脏页和 checkpoint
SHOW ENGINE INNODB STATUS\G
-- BUFFER POOL AND MEMORY 段:Dirty pages 数量
-- LOG 段:Log sequence number / Log flushed up to / Pages flushed up to

追问

  • 问:刷脏页会阻塞业务吗?答:大量刷时占 IO 带宽,业务慢查询增多;大促前要预热 + 控刷脏速度。
  • 问:怎么调刷脏速度?答:innodb_io_capacity、innodb_io_capacity_max,SSD 可设大(如 2000),机械盘小(200)。

题目 10:WAL 预写日志是怎么回事?

考点

  • Write-Ahead Logging;
  • 先写 redo log 再改数据页;
  • 保证持久性。

参考答案

  • WAL(Write-Ahead Logging):修改数据时,先把修改写到 redo log(顺序写),再改内存页;redo log 落盘后才返回 COMMIT 成功;
  • 数据页本身的修改(随机写磁盘)由后台异步刷;
  • 优点:

1. 把随机写数据页变成顺序写 redo log,性能高;

2. 宕机时靠 redo log 重放,不丢已提交事务;

  • 这是 InnoDB 持久性的核心(见第 3 章)。
-- WAL 流程:
-- 1. 修改 Buffer Pool 数据页(标记脏)
-- 2. 写 redo log buffer
-- 3. commit 时 redo log 刷盘(fsync)
-- 4. 返回成功
-- 5. 后台慢慢把脏页刷到数据文件

追问

  • 问:redo log 是顺序写还是随机写?答:顺序写,固定文件循环追加,这是它快的原因。
  • 问:数据页写盘是顺序还是随机?答:随机写,所以慢,靠 Buffer Pool 缓存吸收。

题目 11:redo log 写满会怎样?

考点

  • 循环写;
  • 写满触发 forced checkpoint;
  • 业务阻塞。

参考答案

  • redo log 是固定大小的循环文件(如 2 个 1GB 文件);
  • 写满时,InnoDB 必须推进 checkpoint:把 checkpoint 之前的脏页全部刷盘,否则新的 redo 没地方写;
  • 这叫 forced checkpoint,此时业务写入被阻塞,直到脏页刷出空间;
  • 大促前要检查 redo log 大小,太小会频繁触发阻塞。
SHOW VARIABLES LIKE 'innodb_log_file_size';        -- 单个 redo 文件大小
SHOW VARIABLES LIKE 'innodb_log_files_in_group';   -- 文件个数,默认 2
-- 总 redo = file_size × files_in_group

追问

  • 问:redo log 多大合适?答:1~4GB,能撑 10 分钟以上写入,避免频繁 forced checkpoint;8.0.30+ 支持动态调整。
  • 问:怎么知道是不是写满了?答:SHOW ENGINE INNODB STATUS 的 LOG 段,checkpoint age 接近总 redo 大小就要警惕。

题目 12:InnoDB 页大小为什么是 16K?

考点

  • 页 = IO 最小单位;
  • 与磁盘、B+ 树扇出的权衡;
  • 可改但不建议。

参考答案

  • InnoDB 默认页大小 16KB,是磁盘 IO 和 Buffer Pool 的最小单位;
  • 为什么是 16K:

1. B+ 树非叶子节点一页能存更多键(扇出大),树高 3 层能覆盖亿级行;

2. 与磁盘块(4K)对齐,4 倍于块大小,减少读放大;

3. 与 OS page cache 配合好;

  • 理论上可改(4K/8K/16K/32K/64K),但要初始化时指定,生产几乎不改。
SHOW VARIABLES LIKE 'innodb_page_size';   -- 16384

追问

  • 问:页越大越好吗?答:页大扇出大但单页 IO 成本高、缓存效率低;16K 是经验值。
  • 问:一行超过 16K 怎么办?答:大字段(TEXT/BLOB)存页外(off-page),页内只留前缀和指针。

题目 13:怎么看 InnoDB 运行状态?SHOW ENGINE INNODB STATUS

考点

  • 重要段落;
  • TRANSACTIONS / BUFFER POOL / LOG / ROW OPERATIONS;
  • 实战排查入口。

参考答案

SHOW ENGINE INNODB STATUS\G 输出重要段落:

| 段落 | 看什么 |

|---|---|

| BACKGROUND THREAD | 主线程状态、pending IO |

| SEMAPHORES | 锁等待、信号量竞争(高并发瓶颈) |

| TRANSACTIONS | 长事务、history list length |

| FILE I/O | IO 读写等待 |

| INSERT BUFFER AND ADAPTIVE HASH INDEX | change buffer、AHI 命中率 |

| LOG | redo 写入、checkpoint age |

| BUFFER POOL AND MEMORY | 脏页数、空闲页数、命中率 |

| ROW OPERATIONS | 当前 SQL、读写行数 |

  • 线上排查第一入口;关键指标有异常要进一步查。

追问

  • 问:输出太长怎么办?答:innodb_status_output_locks=ON 打印锁;也可以查 performance_schema 各表。
  • 问:history list length 多少算高?答:持续 > 100 万要查长事务。

题目 14:Buffer Pool 命中率怎么算?低了怎么办?

考点

  • 命中率公式;
  • 低 = 内存不够或访问模式差;
  • 解决:加内存、优化查询。

参考答案

  • 命中率公式:
  命中率 = 1 - Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests
  • read_requests:逻辑读(Buffer Pool 命中请求);
  • reads:物理读(磁盘读页次数);
  • 健康的数据库命中率应 > 99%;
  • 低了怎么办:

1. 内存不够 → 调大 innodb_buffer_pool_size;

2. 全表扫描太多 → 加索引,避免大查询污染缓冲池;

3. 冷数据多 → 考虑分区、归档。

SHOW STATUS LIKE 'Innodb_buffer_pool_read_requests';
SHOW STATUS LIKE 'Innodb_buffer_pool_reads';
-- 算命中率:
-- 1 - reads / read_requests

追问

  • 问:全表扫描会污染 Buffer Pool 吗?答:会,InnoDB 用 midpoint LRU 把全表扫描读到的页放 young 区末尾,快速淘汰,减少污染。
  • 问:命中率 95% 算低吗?答:看数据量,小库 95% 也正常;大库要求 99%+。

题目 15:临出问题时 InnoDB 有哪些关键监控指标?

考点

  • 缓冲池命中;
  • 行锁等待;
  • history list;
  • checkpoint age。

参考答案

线上 InnoDB 必看指标:

| 指标 | 查看方式 | 健康值 |

|---|---|---|

| Buffer Pool 命中率 | SHOW STATUS | > 99% |

| 脏页比例 | BUFFER POOL 段 | < 10% |

| history list length | TRANSACTIONS 段 | < 100 万 |

| 行锁等待数 | Innodb_row_lock_waits | 平稳不暴涨 |

| checkpoint age | LOG 段 | < 70% redo 总量 |

| 活跃事务数 | INNODB_TRX | < 几十 |

  • 这些指标接 Prometheus/Grafana 告警,是 DBA 日常。
SHOW GLOBAL STATUS LIKE 'Innodb_row_lock_waits';
SHOW GLOBAL STATUS LIKE 'Innodb_row_lock_time_avg';

追问

  • 问:脏页比例高怎么办?答:调大 innodb_io_capacity 让刷脏更快,或降低写入峰值。
  • 问:行锁等待暴涨说明什么?答:热点行并发写冲突,要业务侧拆分。

题目 16:InnoDB 内存结构和磁盘结构怎么协同?

考点

  • 读路径;
  • 写路径;
  • 一致性保证。

参考答案

读路径:

1. 查 Buffer Pool 是否有目标页;

2. 命中 → 直接返回(MVCC 判断版本);

3. 未命中 → 从磁盘读页进 Buffer Pool,再返回。

写路径:

1. 找到目标页(不在则读入 Buffer Pool);

2. 修改内存页,标记脏;

3. 写 redo log buffer;

4. commit 时 redo 刷盘;

5. 后台 page cleaner 异步把脏页刷到磁盘。

  • 一致性:redo log 保证崩溃恢复,doublewrite 保证页不半写,MVCC 保证读一致。

追问

  • 问:为什么写不直接刷磁盘?答:随机写太慢,靠 Buffer Pool 攒批 + redo 顺序写,吞吐提升百倍。
  • 问:宕机丢数据吗?答:已 commit 的事务 redo 已刷盘,重启重放不丢;未 commit 的靠 undo 回滚。

InnoDB 架构速查表

| 组件 | 位置 | 作用 | 关键参数 |

|---|---|---|---|

| Buffer Pool | 内存 | 缓存数据/索引页 | innodb_buffer_pool_size |

| Change Buffer | 内存 | 二级索引写合并 | innodb_change_buffer_max_size |

| Log Buffer | 内存 | redo 缓冲 | innodb_log_buffer_size |

| AHI | 内存 | 热点等值哈希加速 | innodb_adaptive_hash_index |

| doublewrite | 磁盘 | 防半页写 | innodb_doublewrite |

| redo log | 磁盘 | WAL 崩溃恢复 | innodb_log_file_size |

| undo log | 磁盘 | 回滚 + MVCC | 独立表空间 |

| 页 | 磁盘 | IO 最小单位 16K | innodb_page_size |

| 读/写路径 | 步骤 |

|---|---|

| 读 | Buffer Pool 命中 → 返回;未命中 → 读页进内存 → MVCC 判断 |

| 写 | 改内存页(脏)→ 写 redo buffer → commit 刷 redo → 后台刷脏页 |

常见坑与注意事项

1. Buffer Pool 设成物理内存 90%+:OS 和连接没内存用,swap 一发整机卡。

2. redo log 太小:高并发下 forced checkpoint 频繁,业务写入抖动。

3. change buffer 被误以为是 undo:它是二级索引写缓冲,不是回滚日志。

4. doublewrite 关掉图快:断电半页写,恢复时页损坏,数据丢失风险。

5. 大查询跑在业务高峰:全表扫描把 Buffer Pool 污染,热点页被挤出,命中率骤降。

6. history list length 暴涨不查:长事务拖 undo,磁盘写满。

7. 以为 Buffer Pool 命中率 100% 才好:100% 反而可能说明数据量小于内存,要关注增长趋势。

复习清单

| 题目 | 核心结论 | 易错点 |

|---|---|---|

| 架构分层 | 内存 + 磁盘 + 后台线程 | 漏了 change buffer |

| Buffer Pool | 数据页缓存,50~70% 内存 | 与 OS cache 混淆 |

| Change Buffer | 二级索引写合并 | 唯一索引不用 |

| doublewrite | 防半页写 | 以为 redo 能替代 |

| WAL | 先写 redo 再改页 | 顺序写 redo 随机写页 |

| 脏页刷盘 | 异步 + checkpoint | 忘了 doublewrite |

| redo 写满 | forced checkpoint 阻塞写 | 以为 redo 会自动 truncate |

| 页大小 | 16K,IO 最小单位 | 答成 4K |

| 命中率 | 1 - reads/read_requests | 公式记反 |

| 长事务 | 拖 purge,undo 暴涨 | 只读事务不算 |

练习题

练 1:一台 32GB 内存的数据库服务器,innodb_buffer_pool_size 设多少合适?为什么?

<details>

<summary>参考答案</summary>

建议 18~22GB(物理内存的 50%~70%)。留 30%~50% 给 OS page cache、连接线程、临时表、系统进程。全给 Buffer Pool 会导致 OS 缺内存触发 swap,整机性能暴跌。8.0 可拆成多个 instance(如 4×5GB)减少锁竞争。

</details>

练 2:写入高峰时业务突然变慢,SHOW ENGINE INNODB STATUS 看到 LOG 段 checkpoint age 接近 redo 总大小。这是什么问题?怎么缓解?

<details>

<summary>参考答案</summary>

redo log 写满触发 forced checkpoint,page cleaner 必须拼命刷脏页才能腾出 redo 空间,IO 打满,业务写入阻塞。缓解:

1. 临时调大 innodb_io_capacity/max 让刷脏更快;

2. 调大 redo log 大小(8.0.30+ 在线调);

3. 业务侧削峰,避免瞬时写入尖峰。

</details>

练 3:为什么 InnoDB 写性能比 MyISAM 好?从架构上解释。

<details>

<summary>参考答案</summary>

MyISAM 只有表锁,写一来全堵;InnoDB:

1. 行锁,写不互斥不同行;

2. WAL:写先到 redo(顺序写)+ Buffer Pool,commit 快;

3. Change Buffer 把二级索引随机写合并;

4. 脏页异步刷盘,不等 IO。

综合下来写并发远高于 MyISAM。

</details>

下一篇预告:第 8 章 存储引擎对比与选型面试精讲

— 全文完 —回到顶部 ↑
下载推广海报

文章推广海报

《第 7 章 InnoDB架构面试精讲》完整推广海报
DISCUSSION

文章回复

0 条公开回复
未登录回复需要审核后公开
还没有回复,欢迎参与讨论。