MySQL 8.0 面试题集
生成时间:2026-06-07
覆盖主题:InnoDB架构、索引优化、事务隔离级别、MVCC机制、锁机制、SQL优化、主从复制、分库分表、窗口函数、CTE、JSON支持、性能调优
题目 1:请描述 InnoDB 存储引擎的架构组成,并说明 Buffer Pool 的作用
难度: ⭐⭐⭐
标准答案:
InnoDB 架构分为内存架构和磁盘架构两大部分:
内存架构:
- Buffer Pool:核心内存区域,缓存表数据与索引数据,采用 LRU 算法管理页的生命周期,显著减少磁盘 I/O
- Redo Log Buffer:缓存即将写入 redo log 的数据,按事务提交频率刷新到磁盘
- Change Buffer:缓存对非唯一索引的二级索引页的写操作(当该页不在 Buffer Pool 中时),减少随机 I/O
磁盘架构:
- 表空间(Tablespace):系统表空间(ibdata)、独立表空间(.ibd 文件)、通用表空间
- Redo Log:保证事务持久性的物理日志,采用循环写入方式
- Undo Tablespace:存储 undo log,用于事务回滚和 MVCC 读取
Buffer Pool 的核心作用:
- 缓存数据页和索引页,读请求优先命中内存
- 写操作先修改 Buffer Pool 中的页(脏页),由后台线程异步刷盘(Write-Back 机制)
- 通过
innodb_buffer_pool_size配置,通常设置为物理内存的 60%-80%
延伸思考:
- Buffer Pool 的 LRU 链表分为 Young 区和 Old 区,如何防止全表扫描污染 Buffer Pool?
- 如何监控 Buffer Pool 的命中率?相关指标有哪些(Innodb_buffer_pool_read_requests / Innodb_buffer_pool_reads)?
题目 2:MySQL 的索引结构是什么?为什么 InnoDB 选择 B+Tree 而不是 B-Tree 或哈希?
难度: ⭐⭐
标准答案:
InnoDB 使用 B+Tree 作为索引结构(聚簇索引的叶子节点存储完整行数据,二级索引的叶子节点存储主键值)。
为什么选择 B+Tree:
| 对比维度 | B-Tree | B+Tree | 哈希索引 |
|---|---|---|---|
| 叶子节点链接 | 无 | 有双向链表 | 无 |
| 非叶子节点存数据 | 是 | 否(只存键) | - |
| 范围查询 | 效率低(需中序遍历) | 极高(链表顺序扫描) | 不支持 |
| 磁盘 I/O | 较高 | 更低(扇出更大) | 最低(等值查询) |
| 有序性 | 部分 | 完全有序 | 无序 |
核心原因:
- 磁盘预读特性:B+Tree 的非叶子节点只存键,相同空间可存更多索引项,树高更低(通常 3-4 层),减少磁盘 I/O 次数
- 范围查询优势:叶子节点通过双向链表连接,范围查询只需遍历链表
- 稳定查询性能:每次查询的路径长度相同(树高固定),时间复杂度稳定为 O(logN)
延伸思考:
- 什么场景下哈希索引更优?Memory 引擎的适用场景?
- 为什么 Like '%abc' 无法使用 B+Tree 索引?而 Like 'abc%' 可以?
题目 3:请详细解释 MySQL 的四种事务隔离级别,以及 MySQL 默认级别是什么?为什么?
难度: ⭐⭐
标准答案:
| 隔离级别 | 脏读 | 不可重复读 | 幻读 | 实现机制 |
|---|---|---|---|---|
| READ UNCOMMITTED(读未提交) | ✗ 可能 | ✗ 可能 | ✗ 可能 | 无锁,直接读最新数据 |
| READ COMMITTED(读已提交) | ✓ 解决 | ✗ 可能 | ✗ 可能 | MVCC,每次读取最新快照 |
| REPEATABLE READ(可重复读) | ✓ 解决 | ✓ 解决 | ✗ 可能(InnoDB 通过 Next-Key Lock 解决) | MVCC + Next-Key Lock |
| SERIALIZABLE(串行化) | ✓ 解决 | ✓ 解决 | ✓ 解决 | 所有读加共享锁 |
MySQL 默认隔离级别:REPEATABLE READ(可重复读)
原因:
- RR 级别下,InnoDB 通过 MVCC(多版本并发控制) 保证同一事务内多次读取结果一致
- InnoDB 在 RR 级别下通过 Next-Key Lock(行锁 + 间隙锁) 解决了幻读问题,达到了 SQL 标准的 Serializable 级别的效果
- 相比 Serializable,RR 的并发性能更好,是性能与一致性的最佳平衡点
查看/设置隔离级别:
-- 查看
SELECT @@transaction_isolation;
-- 设置会话级别
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;延伸思考:
- RC 和 RR 在 MVCC 实现上有什么本质区别?(Read View 创建时机不同)
- 什么业务场景应该使用 RC 而不是默认的 RR?
题目 4:请深入解释 InnoDB 的 MVCC 机制是如何实现的?
难度: ⭐⭐⭐
标准答案:
MVCC(Multi-Version Concurrency Control)通过在每行记录中保存多个版本,实现非锁定一致性读。
核心实现:隐藏字段 + Undo Log + Read View
每行记录的三个隐藏字段:
DB_TRX_ID(6字节):最后修改该行的事务 IDDB_ROLL_PTR(7字节):回滚指针,指向 undo log 中该行的上一个版本DB_ROW_ID(6字节):行 ID,表没有主键时自动生成聚簇索引
Undo Log 版本链:
- 每次修改记录时,将原值写入 undo log,通过
DB_ROLL_PTR形成版本链 - 不同事务读取时,根据自身的 Read View 在版本链中找到对其可见的版本
Read View(一致性视图): Read View 在事务第一次执行快照读时创建,包含四个重要属性:
m_ids:生成 Read View 时活跃的事务 ID 列表min_trx_id:m_ids 中的最小值max_trx_id:生成 Read View 时系统应该分配给下一个事务的 IDcreator_trx_id:创建该 Read View 的事务 ID
可见性判断算法:
if (记录 DB_TRX_ID < min_trx_id) → 该版本在 Read View 创建前已提交,可见
if (记录 DB_TRX_ID >= max_trx_id) → 该版本是 Read View 创建后新开的事务修改的,不可见
if (min_trx_id <= DB_TRX_ID < max_trx_id):
if (DB_TRX_ID in m_ids) → 该事务在 Read View 创建时还未提交,不可见
else → 已提交,可见
if (DB_TRX_ID == creator_trx_id) → 自己修改的,可见RC 与 RR 的关键区别:
- RC(读已提交):每次执行 SELECT 时都生成新的 Read View → 能读到其他事务已提交的修改
- RR(可重复读):事务开始时生成一次 Read View,整个事务期间复用 → 保证可重复读
延伸思考:
- 为什么长事务会导致 undo log 膨胀?应如何监控和处理?
purge线程的作用是什么?什么情况下历史版本无法被清理?
题目 5:InnoDB 的锁机制有哪些类型?请详细解释意向锁、记录锁、间隙锁、临键锁的区别和使用场景
难度: ⭐⭐⭐
标准答案:
锁的分类维度:
按粒度分:
- 表级锁:
LOCK TABLES(显式)、意向锁(Intention Lock,InnoDB 自动加) - 行级锁:记录锁(Record Lock)、间隙锁(Gap Lock)、临键锁(Next-Key Lock)
按模式分:
- 共享锁(S Lock):
SELECT ... LOCK IN SHARE MODE - 排他锁(X Lock):
SELECT ... FOR UPDATE、UPDATE、DELETE - 意向共享锁(IS):事务准备加 S 锁时,自动在表级别加 IS
- 意向排他锁(IX):事务准备加 X 锁时,自动在表级别加 IX
核心锁类型详解:
| 锁类型 | 作用范围 | 目的 | 示例 |
|---|---|---|---|
| 记录锁(Record Lock) | 锁定索引记录本身 | 防止其他事务修改/删除该行 | SELECT * FROM t WHERE id=5 FOR UPDATE |
| 间隙锁(Gap Lock) | 锁定索引记录之间的间隙 | 防止其他事务插入数据(解决幻读) | RR 级别下范围查询时自动加 |
| 临键锁(Next-Key Lock) | 记录锁 + 间隙锁(左开右闭) | InnoDB RR 级别的默认行锁算法 | 锁定 (5, 10] 这个区间 |
| 意向锁(Intention Lock) | 表级别,不与行锁冲突 | 快速判断表中是否有行被锁定,避免逐行检查 | 自动加,无需手动干预 |
Next-Key Lock 详解:
- 是 InnoDB 在 RR 级别下默认的行锁算法
- 锁定范围是「索引记录 + 该记录前面的间隙」,即
(prev_key, current_key] - 示例:索引值为
[5, 10, 15],对id=10加 Next-Key Lock,锁定范围是(5, 10] - 唯一索引上的等值查询会降级为记录锁(不会加间隙锁),只有范围查询或非唯一索引才会触发 Next-Key Lock
意向锁的作用:
- 当事务 A 锁定了表中的某一行(加 X 锁),同时会在表级别加 IX 锁
- 此时事务 B 想对整张表加表级 X 锁,
LOCK TABLES t WRITE,会检查表上是否有意向锁 - 如果有(事务 A 已加 IX),则事务 B 阻塞,避免表锁与行锁的冲突
锁兼容矩阵:
| IS | IX | S | X | |
|---|---|---|---|---|
| IS | ✓ | ✓ | ✓ | ✗ |
| IX | ✓ | ✓ | ✗ | ✗ |
| S | ✓ | ✗ | ✓ | ✗ |
| X | ✗ | ✗ | ✗ | ✗ |
延伸思考:
- 什么情况下 InnoDB 的锁会从行锁升级为表锁?(未命中索引时)
- 如何查看当前 InnoDB 的锁等待情况?(
information_schema.INNODB_LOCKS、INNODB_LOCK_WAITS) - MySQL 8.0 中
performance_schema.data_locks和data_lock_waits如何替代了旧的INNODB_LOCKS表?
题目 6:请列举至少 5 条 SQL 优化的实战经验,并结合 EXPLAIN 说明如何分析慢查询
难度: ⭐⭐
标准答案:
SQL 优化实战经验:
- 最左前缀原则:联合索引
(a, b, c),只有查询条件包含a,或a,b时才能命中索引;b,c无法命中 - 避免索引失效的场景:
- 对索引列使用函数或运算:
WHERE YEAR(create_time) = 2024(失效)vsWHERE create_time >= '2024-01-01'(生效) - 隐式类型转换:
WHERE varchar_col = 123(字符串列等于数字,触发类型转换,索引失效) LIKE '%xxx'(左模糊)无法使用索引;LIKE 'xxx%'(右模糊)可以使用索引OR条件中有一列不含索引,则整个 SQL 无法使用索引
- 对索引列使用函数或运算:
- 覆盖索引:查询列尽量包含在索引中,避免回表(
Using index在 Extra 列中) - 小表驱动大表:
IN适合子查询返回小结果集;EXISTS适合子查询返回大结果集 - LIMIT 大偏移量优化:
LIMIT 100000, 20性能极差,改为游标分页:WHERE id > 100000 LIMIT 20
EXPLAIN 关键字段解读:
| 字段 | 说明 | 重点关注 |
|---|---|---|
id | 查询序号 | 越大越先执行;相同 id 从上到下执行 |
select_type | 查询类型 | SIMPLE(简单查询)、PRIMARY(主查询)、SUBQUERY(子查询) |
type | 访问类型(重要!) | 性能排序:system > const > eq_ref > ref > range > index > ALL;至少要达到 range 级别 |
key | 实际使用的索引 | 为 NULL 表示未使用索引 |
rows | 预估扫描行数 | 越小越好 |
Extra | 附加信息 | Using filesort(需要优化排序)、Using temporary(需要优化 GROUP BY)、Using index(覆盖索引,好) |
慢查询分析步骤:
- 开启慢查询日志:
SET GLOBAL slow_query_log = 'ON'; - 用
EXPLAIN或EXPLAIN FORMAT=JSON分析执行计划 - 关注
type=ALL(全表扫描)、rows过大、Extra含Using filesort/Using temporary - 通过
SHOW PROFILE(MySQL 8.0 推荐使用performance_schema)查看各阶段耗时
延伸思考:
ref和eq_ref的区别是什么?- 如何判断是优化 SQL 还是增加硬件资源(Scale Up vs Scale Out)?
题目 7:MySQL 主从复制的原理是什么?有哪些常见的复制模式?如何解决主从延迟问题?
难度: ⭐⭐⭐
标准答案:
主从复制原理(基于 Binlog):
主库(Master) 从库(Slave)
│ │
├── 1. 数据变更写入 Binlog ──────────────┐ │
│ (Binary Log,逻辑/物理日志) │ │
│ ▼ │
│ 2. IO 线程拉取 Binlog │
│ │ │
│ ▼ │
│ 3. 写入从库的中继日志(Relay Log)│
│ │ │
│ ▼ │
│ 4. SQL 线程重放 Relay Log │
│ │ │
│ ▼ │
└──────────────── 5. 从库数据与主库一致 ◄───┘三种 Binlog 格式:
| 格式 | 说明 | 优点 | 缺点 |
|---|---|---|---|
| STATEMENT | 记录 SQL 语句 | 日志量小 | 部分函数(如 UUID()、NOW())在主从执行结果不一致 |
| ROW | 记录每行数据的变化 | 数据一致性最高,主从完全一致 | 日志量大(大批量更新时尤为明显) |
| MIXED | 混合模式,MySQL 自动选择 | 平衡日志量和一致性 | - |
MySQL 8.0 默认使用 ROW 格式,推荐生产环境也使用 ROW。
常见复制模式:
- 异步复制(默认):主库写入 Binlog 后立即返回,不等待从库确认 → 性能最好,但存在数据丢失风险
- 半同步复制(Semi-Sync):主库至少等待一个从库接收(不一定要执行)Binlog 后才返回 → 平衡性能与数据安全
- 组复制(Group Replication,MySQL 8.0 推荐):基于 Paxos 协议,支持多主写入,自动故障检测
主从延迟的常见原因及解决方案:
| 原因 | 解决方案 |
|---|---|
| 从库硬件性能差于主库 | 提升从库硬件规格,保持与主库一致 |
| 从库单 SQL 线程重放(MySQL 5.6 之前) | 开启并行复制:slave_parallel_workers > 0 |
| 大事务导致从库长时间阻塞 | 避免大事务,拆分为小事务 |
| 从库读压力太大,复制线程被阻塞 | 读写分离,增加从库实例;或启用多线程复制 |
| 网络延迟 | 优化主从之间的网络(同机房/同可用区部署) |
并行复制(MySQL 8.0):
-- 开启并行复制(基于 WRITESET 的并行复制,性能最好)
SET GLOBAL binlog_transaction_dependency_tracking = 'WRITESET';
SET GLOBAL transaction_write_set_extraction = 'XXHASH64';
SET GLOBAL slave_parallel_workers = 8;
SET GLOBAL slave_preserve_commit_order = 1;延伸思考:
- 如何监控主从延迟?(
SHOW SLAVE STATUS中的Seconds_Behind_Master;更准确的方式是对比主从的 Binlog 位点) - 半同步复制在什么情况下会退化为异步复制?如何避免?
题目 8:什么场景需要做分库分表?分库分表有哪些常见方案?分库分表后带来了哪些新的问题?
难度: ⭐⭐⭐
标准答案:
分库分表的触发条件(先做这些,再考虑分库分表):
- 单表数据量超过 500万-2000万行(取决于硬件和业务场景)
- 数据库写入/读取的 QPS 达到单机上限
- 数据库已成为系统瓶颈,且无法通过 SQL 优化、升级硬件、读写分离解决
⚠️ 分库分表是重量级方案,会带来极大复杂度,应作为最后手段。
分库分表方案:
① 垂直拆分:
- 垂直分库:按业务模块拆分(用户库、订单库、商品库),不同业务使用独立数据库
- 垂直分表:将宽表中不常用的字段拆分到扩展表(如用户表拆分为
user_base+user_profile)
② 水平拆分(Sharding):
- 水平分表:同一数据库内,将一张表按某个字段(如
user_id)取模或按范围拆分到多张表order_202401、order_202402(按时间范围)user_0~user_15(按user_id % 16取模)
- 水平分库分表:将拆分后的表分布到不同数据库实例,实现真正的横向扩展
分片键(Sharding Key)选择原则:
- 尽量选择查询频率最高的字段作为分片键
- 避免数据倾斜(如用新用户注册时间分片,可能导致某段时间数据过热)
- 避免跨分片查询(无法使用 JOIN、分布式事务等问题)
分库分表后的新问题:
| 问题 | 说明 | 解决方案 |
|---|---|---|
| 分布式事务 | 跨库更新无法用本地事务保证 ACID | 两阶段提交(2PC)、TCC、Saga 模式;或使用 Seata 框架 |
| 跨分片查询 | 无法 JOIN 不同分片的表 | 字段冗余(空间换时间)、全局表(小表广播)、应用层聚合 |
| 分页查询 | LIMIT 需要每个分片都查询再合并 | 禁用深分页;使用游标分页(WHERE id > ? LIMIT n) |
| 分片键以外的查询 | 无法定位到具体分片,需要全量扫描 | 建立映射表(基因法)、使用 ES 做全文检索 |
| 数据迁移与扩容 | 增加分片数量需要重新分片 | 一致性哈希(扩容时只迁移少量数据);提前预留足够分片 |
| ID 生成 | 自增 ID 在分库分表下会冲突 | 雪花算法(Snowflake)、号段模式、UUID |
延伸思考:
- 新项目应该如何设计,才能在未来需要分库分表时尽可能平滑迁移?
- 分库分表与 NewSQL(TiDB、CockroachDB)的选择标准是什么?
题目 9:MySQL 8.0 引入了哪些重要的新特性?请重点介绍窗口函数、CTE 和 JSON 增强
难度: ⭐⭐
标准答案:
MySQL 8.0 核心新特性:
一、窗口函数(Window Functions)
窗口函数在不减少原表行数的前提下,对一组相关行进行计算。
语法:
<窗口函数>() OVER (
PARTITION BY <分组列>
ORDER BY <排序列>
[ROWS|RANGE <窗口框架>]
)常用窗口函数:
| 类别 | 函数 | 说明 |
|---|---|---|
| 排序 | ROW_NUMBER() | 行号(不并列) |
| 排序 | RANK() | 排名(并列跳过,如 1,1,3) |
| 排序 | DENSE_RANK() | 密集排名(并列不跳过,如 1,1,2) |
| 取值 | LAG(col, n) | 取前第 n 行的值 |
| 取值 | LEAD(col, n) | 取后第 n 行的值 |
| 取值 | FIRST_VALUE(col) | 取窗口第一行的值 |
| 聚合 | SUM()/AVG()/COUNT() OVER(...) | 聚合函数 + 窗口 |
实战示例:
-- 查询每个部门工资排名前 3 的员工
SELECT *
FROM (
SELECT
employee_id,
department_id,
salary,
ROW_NUMBER() OVER (
PARTITION BY department_id
ORDER BY salary DESC
) AS rn
FROM employees
) t
WHERE rn <= 3;
-- 计算同比/环比(LAG 取上一行)
SELECT
month,
revenue,
LAG(revenue, 1) OVER (ORDER BY month) AS prev_month_revenue,
ROUND((revenue - LAG(revenue, 1) OVER (ORDER BY month)) / LAG(revenue, 1) OVER (ORDER BY month) * 100, 2) AS growth_rate
FROM monthly_revenue;二、CTE(Common Table Expression,公用表表达式)
语法:
WITH cte_name AS (
SELECT ... -- CTE 定义
)
SELECT * FROM cte_name;递归 CTE(MySQL 8.0 重要增强):
-- 查询组织架构树(查找所有下属)
WITH RECURSIVE subordinates AS (
-- 锚定成员:从指定员工开始
SELECT id, name, manager_id, 0 AS level
FROM employees
WHERE id = 1
UNION ALL
-- 递归成员:查找直接下属
SELECT e.id, e.name, e.manager_id, s.level + 1
FROM employees e
INNER JOIN subordinates s ON e.manager_id = s.id
)
SELECT * FROM subordinates;CTE vs 子查询:
- CTE 提高可读性(尤其是复杂多层子查询)
- CTE 可以自引用(递归 CTE)
- MySQL 8.0 的 CTE 是物化的(临时表),多次引用同一 CTE 不会重复计算
三、JSON 增强
MySQL 5.7 已支持 JSON,但 MySQL 8.0 大幅增强:
核心 JSON 函数:
-- 创建 JSON 列
CREATE TABLE orders (
id INT PRIMARY KEY,
info JSON
);
-- 插入 JSON 数据
INSERT INTO orders VALUES (1, '{"user_id": 100, "items": [{"sku": "A", "qty": 2}], "total": 199.99}');
-- 提取 JSON 值(-> 返回带引号的字符串,->> 返回去引号的值)
SELECT info->>"$.user_id" AS user_id FROM orders;
SELECT JSON_EXTRACT(info, "$.total") FROM orders;
-- 修改 JSON(部分更新,无需反序列化整个文档)
UPDATE orders SET info = JSON_SET(info, "$.total", 299.99) WHERE id = 1;
UPDATE orders SET info = JSON_REMOVE(info, "$.items") WHERE id = 1;
-- JSON 路径表达式
SELECT * FROM orders WHERE JSON_CONTAINS(info, "100", "$.user_id");
SELECT * FROM orders WHERE info->>"$.user_id" = "100";
-- JSON_TABLE:将 JSON 数组转换为关系型行(8.0 新特性)
SELECT *
FROM orders,
JSON_TABLE(info, "$.items[*]"
COLUMNS (
sku VARCHAR(50) PATH "$.sku",
qty INT PATH "$.qty"
)
) AS items;JSON + 索引:
- MySQL 8.0 支持对 JSON 列中的字段创建虚拟列 + 索引:
ALTER TABLE orders
ADD COLUMN user_id INT GENERATED ALWAYS AS (info->>"$.user_id") VIRTUAL,
ADD INDEX idx_user_id (user_id);延伸思考:
- 窗口函数中
ROWS和RANGE的区别是什么? - JSON 存储在 MySQL 中 vs 独立文档数据库(MongoDB)的选择标准?
题目 10:如何从全局角度对 MySQL 进行性能调优?请列举关键的配置参数和优化思路
难度: ⭐⭐⭐
标准答案:
MySQL 性能调优分层思路:
应用层 → SQL 层 → 存储引擎层(InnoDB)→ 操作系统层 → 硬件层一、InnoDB 核心参数调优:
| 参数 | 建议值 | 说明 |
|---|---|---|
innodb_buffer_pool_size | 物理内存的 60%-80% | Buffer Pool 大小,最核心的参数 |
innodb_buffer_pool_instances | 8(或 CPU 核数) | 将 Buffer Pool 拆分为多个实例,减少锁竞争 |
innodb_log_file_size | 1GB-2GB | Redo log 文件大小,越大则刷盘频率越低,写入性能越好;但崩溃恢复时间更长 |
innodb_flush_log_at_trx_commit | 2(高性能)/ 1(高安全) | 0=每秒刷盘;1=每次提交刷盘(最安全,默认);2=每次提交写 OS cache,每秒刷盘 |
innodb_flush_method | O_DIRECT(Linux) | 绕过 OS 文件系统缓存,避免双缓存(OS Cache + Buffer Pool) |
innodb_io_capacity | SSD: 2000-5000;NVMe: 10000+ | 告诉 InnoDB 存储设备的 IOPS 能力,影响脏页刷新速度 |
innodb_io_capacity_max | innodb_io_capacity * 2 | 后台刷脏页的最大 IOPS |
innodb_read_io_threads | 8 | 读 IO 线程数 |
innodb_write_io_threads | 8 | 写 IO 线程数 |
innodb_purge_threads | 4 | Purge(清理 undo log)线程数 |
innodb_change_buffering | all | 开启 Change Buffer,缓存二级索引的写操作 |
innodb_page_cleaners | innodb_buffer_pool_instances | 脏页清理线程数 |
二、连接与线程调优:
| 参数 | 建议值 | 说明 |
|---|---|---|
max_connections | 根据业务估算(如 500-1000) | 最大连接数,不是越大越好 |
thread_cache_size | 根据 Threads_created / Connections 比例调整 | 缓存线程,避免频繁创建销毁线程 |
wait_timeout | 300-600(秒) | 非交互连接空闲超时,避免长连接占用 |
interactive_timeout | 300-600 | 交互连接(如 MySQL 客户端)空闲超时 |
三、查询缓存(⚠️ 注意):
MySQL 8.0 已完全移除查询缓存(Query Cache),因为在高并发场景下锁竞争严重,且数据变更会导致缓存失效。替代方案:应用层缓存(Redis/Memcached)。
四、Binlog 与复制调优:
| 参数 | 建议值 | 说明 |
|---|---|---|
binlog_format | ROW | 8.0 默认 ROW,数据一致性最好 |
binlog_row_image | MINIMAL | ROW 格式下只记录变更的列,减少 Binlog 体积 |
sync_binlog | 2(高性能)/ 1(高安全) | 控制 Binlog 刷盘频率 |
binlog_group_commit_sync_delay | 0-1000(微秒) | 组提交延迟,提高写入吞吐量 |
slave_parallel_workers | 8-16 | 并行复制线程数 |
binlog_transaction_dependency_tracking | WRITESET | 基于写集合的并行复制,性能最优 |
五、操作系统层面:
# 禁用 swap(避免 MySQL 内存被换出到磁盘)
echo vm.swappiness=1 >> /etc/sysctl.conf
# 文件系统:建议使用 XFS 或 ext4(禁用 atime)
mount -o noatime,nodiratime /dev/sdb /var/lib/mysql
# 调度器:SSD 使用 deadline 或 noop
echo deadline > /sys/block/sda/queue/scheduler六、监控指标(重点):
-- 查看 Buffer Pool 命中率(> 99% 为佳)
SHOW ENGINE INNODB STATUS;
-- 查看连接数
SHOW STATUS LIKE 'Threads_connected';
SHOW STATUS LIKE 'Max_used_connections';
-- 查看慢查询
SHOW STATUS LIKE 'Slow_queries';
-- 查看 InnoDB 行操作
SHOW STATUS LIKE 'Innodb_rows_%';延伸思考:
innodb_flush_log_at_trx_commit = 2在操作系统崩溃时最多丢失多少数据?- 如何判断
innodb_buffer_pool_size是否足够大?(监控Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests比值)
总结
本面试题集覆盖了 MySQL 8.0 的核心知识点,难度从 ⭐ 到 ⭐⭐⭐ 递进,既适合候选人的自我检测,也适合面试官系统评估候选人的 MySQL 功底。
推荐学习路径:
- 先掌握索引和 SQL 优化(日常开发最高频)
- 深入理解事务隔离级别和 MVCC(进阶必考)
- 掌握锁机制和主从复制(高并发场景必备)
- 了解 MySQL 8.0 新特性(窗口函数、CTE、JSON)
- 具备全局性能调优思路(高级/架构师级别)