用途:理解一条 SQL 从连接到落盘经过哪些组件,以及为什么选 InnoDB
| 组件 |
关键点 |
| 连接器 |
长连接与 wait_timeout;连接数上限与线程池;权限在连接时加载 |
| 查询缓存 |
MySQL 8.0 已彻底移除(旧版本命中率低且失效频繁) |
| 执行器 |
逐行调用引擎接口;权限校验在此发生 |
| 存储引擎 |
插件式,行级存储与日志由引擎负责 |
| 结构 |
作用 |
| 缓冲池(Buffer Pool) |
页缓存,读命中避免磁盘 IO;写先改内存页再落盘 |
| redo log |
物理循环日志,保证崩溃恢复与持久性(WAL) |
| undo log |
版本链与回滚,支撑 MVCC 与事务回滚 |
| change buffer |
二级索引非唯一写的合并优化 |
| doublewrite buffer |
防页断裂(partial write) |
| 表空间 |
系统表空间 / 独立表空间 / 通用表空间;页大小默认 16KB |
| 自适应哈希 |
引擎内部按热点等值查询自动构建,不建议依赖或关闭赌性能 |
| 引擎 |
事务 |
行锁 |
外键 |
适用 |
| InnoDB |
支持 |
支持 |
支持 |
默认且几乎唯一合理选择 |
| MyISAM |
不支持 |
表锁 |
不支持 |
只读归档、历史遗留;崩溃易损坏 |
| Memory |
不支持 |
表锁 |
不支持 |
临时聚合,进程重启即丢 |
| RocksDB/MyRocks 插件 |
支持 |
行锁 |
部分 |
写密集、压缩比敏感场景(需运维能力) |
innodb_buffer_pool_size:物理内存的 50-70%(专用数据库主机),是命中率第一影响因素。
innodb_flush_log_at_trx_commit:1(每次提交刷盘,最安全)/2(每秒刷,崩溃丢 1 秒)/0(性能最高、风险最大)。
sync_binlog、innodb_io_capacity、innodb_log_file_size(或 8.0 的 innodb_redo_log_capacity)共同决定写吞吐与恢复时间。
- 连接相关:
max_connections、thread_pool(如使用)、wait_timeout;连接数不是越大越好,超过 CPU 核数后主要变成上下文切换。
| 误区 |
修正 |
| 用 MyISAM 图快 |
表锁与崩溃风险在并发写场景得不偿失 |
| redo log 配得很大只为省刷盘 |
恢复时间与崩溃后回放成本上升 |
| 缓冲池越大越好 |
必须为 OS 页缓存与其他进程留内存,否则 swap 反而剧降性能 |
| 长连接一定优于短连接 |
长连接需配合连接池与空闲回收,否则内存与故障半径变大 |
| 忽视 8.0 与 5.7 的行为差异 |
默认字符集、降序索引、CTE/窗口函数、redo 动态调整、查询缓存移除都影响方案 |
- MySQL 官方文档 InnoDB 章节(Architecture、Buffer Pool、Redo/Undo)
- 《高性能 MySQL》第 4 版(第 1-2 部分)
- 丁奇《MySQL 实战 45 讲》(结构与日志部分)