MySQL 核心原理笔记
整理自技术问答,涵盖 MySQL 架构、日志机制、事务原理、MVCC、锁机制、崩溃恢复、主从复制、SQL调优等核心面试知识点。
一、MySQL 整体架构
1.1 层级划分
1.2 关键认知锚点
Redo Log 是 InnoDB 引擎层的物理日志,记录“在某个数据页的某个偏移量处写入什么值”。
Binlog 是 Server 层的逻辑日志,记录 SQL 语句或行变更,所有存储引擎共用。
Undo Log 是逻辑日志,记录修改前的旧值,用于回滚和 MVCC。
二、三大日志详解
2.1 Redo Log(重做日志)
2.2 Binlog(归档日志)
2.3 Undo Log(回滚日志)
2.4 三种日志职责对比
三、两阶段提交(2PC)
3.1 为什么需要两阶段提交?
核心目标:保证 Redo Log 和 Binlog 的数据一致性,确保主库和从库的数据最终一致,避免事务数据不一致、数据丢失问题。
3.2 两阶段提交流程
事务执行
│
▼
① Redo Log 写入 → 状态标记为 PREPARE
│
▼
② Binlog 写入 → 落盘成功
│
▼
③ Redo Log 状态 → 升级为 COMMIT
│
▼
④ 返回客户端:事务提交成功 ✅3.3 各阶段宕机恢复策略
核心结论:Binlog 是崩溃恢复时的“最终仲裁者”。Binlog 完整 → 提交;Binlog 不完整 → 回滚。
四、一条 UPDATE 语句的完整执行流程
UPDATE users SET age = 25 WHERE id = 1;4.1 完整流程图
客户端发送 UPDATE 语句
│
▼
【Server层】连接器 → 解析器 → 优化器 → 执行器
│
▼
【InnoDB层】加载数据页到 Buffer Pool
│
▼
【InnoDB层】写入 Undo Log(记录旧值,用于回滚)
│
▼
【InnoDB层】修改 Buffer Pool 中的数据页(内存,变为脏页)
│
▼
【InnoDB层】写入 Redo Log(PREPARE,物理修改)
│
▼
【Server层】写入 Binlog(逻辑变更)
│
▼
【InnoDB层】Redo Log 状态升级为 COMMIT(两阶段提交完成)
│
▼
【Server层】返回客户端:执行成功 ✅
│
▼
【后台异步】Redo Log / Binlog 根据刷盘策略落盘
│
▼
【后台异步】脏页刷回磁盘(Checkpoint 触发)4.2 各阶段详解
五、刷盘策略与数据安全性
5.1 Redo Log 刷盘参数
innodb_flush_log_at_trx_commit = 1 -- 每次事务提交强制落盘(最安全,性能最低)
innodb_flush_log_at_trx_commit = 2 -- 每秒落盘(可能丢 1 秒数据)
innodb_flush_log_at_trx_commit = 0 -- 每秒落盘(可能丢 1 秒数据,性能最好)5.2 Binlog 刷盘参数
sync_binlog = 1 -- 每次事务提交强制落盘(最安全)
sync_binlog = 0 -- 由操作系统决定(性能最好,风险最高)
sync_binlog = N -- 每 N 个事务提交后刷盘(可接受少量丢失)5.3 "双一"配置
双一配置 = innodb_flush_log_at_trx_commit=1 + sync_binlog=1
效果:事务提交时,Redo Log 和 Binlog 都强制落盘,实现数据零丢失。
代价:性能开销最大(频繁磁盘 IO)。
适用场景:金融、支付等对数据零丢失有严格要求的系统。
六、主从复制与高可用
6.1 主从复制原理
主库 (Master)
│
├── 事务提交 → 写入 Binlog
│
▼
从库 (Slave) I/O 线程
│
├── 读取主库 Binlog
├── 写入 Relay Log(中继日志)
│
▼
从库 (Slave) SQL 线程
│
├── 读取 Relay Log
├── 重放 SQL → 数据同步完成6.2 主库宕机且 Binlog 丢失时的风险
6.3 预防措施
七、关键参数速查
八、InnoDB vs MyISAM
九、补充:WAL 技术
9.1 什么是 WAL?
WAL(Write-Ahead Logging,预写日志) 是一种确保数据完整性的技术,核心思想是:先写日志,再写数据。
9.2 WAL 为什么能提升性能?
WAL 用快速的顺序日志写,替代了慢速的随机数据页写,大幅提升了数据库写入性能。
十、MVCC 多版本并发控制
10.1 MVCC 核心概念
MVCC(Multi-Version Concurrency Control,多版本并发控制) 是 InnoDB 实现高并发、读写不加锁的核心机制,仅作用于快照读,核心作用是解决读写冲突、实现事务隔离、降低锁竞争。
MVCC 仅存在于 InnoDB 引擎,MyISAM 不支持;主要依托 Undo Log(版本数据) 和 Read View(读视图) 实现。
10.2 核心前置知识
10.2.1 隐藏字段
InnoDB 每条数据行都会自带 3 个隐藏字段,是 MVCC 的基础:
DB_TRX_ID:6 字节,修改当前行数据的最新事务 ID
DB_ROLL_PTR:7 字节,回滚指针,指向 Undo Log 中的上一个旧版本数据
DB_ROW_ID:6 字节,行唯一标识(无主键时使用)
10.2.2 快照读 & 当前读
10.3 版本链机制
当事务多次修改同一行数据时,每次修改都会生成一条 Undo Log 旧版本数据,通过 DB_ROLL_PTR 串联形成版本链。
数据更新流程:修改数据前,先将旧数据存入 Undo Log → 更新内存新数据 → 记录事务 ID 和回滚指针,形成版本链表。
10.4 Read View 读视图
Read View 是事务快照读的核心判断依据,用来筛选版本链中当前事务可见的数据版本,包含 4 个核心字段:
m_ids:当前系统中所有活跃未提交的事务 ID 集合
min_trx_id:m_ids 中的最小事务 ID
max_trx_id:开启当前事务时,系统即将分配的下一个事务 ID
creator_trx_id:当前事务自身的 ID
10.5 版本可见性判断规则
遍历版本链,根据数据版本的 DB_TRX_ID 判断是否可见:
若版本事务ID = 当前事务ID:可见(自己修改的数据)
若版本事务ID < min_trx_id:可见(事务已提交)
若版本事务ID >= max_trx_id:不可见(事务开启后新产生的数据)
若 min_trx_id < 版本事务ID < max_trx_id:判断是否在 m_ids 中,不在则可见,在则不可见
10.6 不同隔离级别下的 MVCC
十一、MySQL 锁机制
11.1 锁的核心作用
数据库锁是解决并发事务竞争资源的核心机制,保障多事务并发操作时的数据一致性、完整性,避免数据脏写、数据错乱。InnoDB 锁机制配合 MVCC,实现了读写分离、读不加锁、写加锁的高并发能力。
11.2 锁的层级分类
11.2.1 表级锁
锁定整张数据表,开销小、加锁快、无死锁,并发极低。
适用引擎:MyISAM 默认表锁,InnoDB 也支持
特点:加锁后其他事务无法读写整表数据
场景:全表更新、批量数据操作
11.2.2 行级锁(InnoDB 核心)
锁定单行数据,开销大、加锁慢、会产生死锁,并发极高。
适用引擎:仅 InnoDB 支持
特点:仅锁定操作行,其他行可正常读写
核心前提:必须走索引!无索引会降级为表锁
11.2.3 元数据锁(MDL)
操作表结构时自动加锁,防止 DDL 与 DML 并发冲突,保证表结构一致性。
11.3 锁的读写分类
11.4 意向锁(InnoDB 特有)
意向锁是表级辅助锁,解决行锁与表锁的冲突检测问题,无需手动加锁,InnoDB 自动维护。
意向共享锁(IS):事务要加行S锁,先加表IS锁
意向排他锁(IX):事务要加行X锁,先加表IX锁
核心作用:快速判断整张表是否存在行锁,避免遍历全表锁,提升锁检测效率。
11.5 特殊锁:间隙锁 & 临键锁(解决幻读)
11.5.1 间隙锁(Gap Lock)
锁定索引数据之间的空白区间,不锁定已有数据,防止其他事务在间隙中插入数据,专门解决幻读问题,仅 RR 隔离级别生效。
11.5.2 临键锁(Next-Key Lock)
InnoDB 默认行锁算法,是 记录锁 + 间隙锁 的结合,锁定当前索引行 + 左侧间隙,彻底杜绝幻读。
11.6 死锁成因与解决
11.6.1 死锁产生四大条件
互斥条件:锁资源独占,不可共享
请求与保持:持有锁的同时请求其他锁
不剥夺条件:锁不会被强制释放
环路等待:多个事务循环等待对方锁资源
11.6.2 死锁解决方案
统一 SQL 执行顺序,避免循环等待
缩短事务生命周期,尽早提交/回滚
避免大事务、批量操作拆分
开启死锁检测,超时自动释放锁
十二、面试高频问答(含 MVCC/锁机制)
Q1:Redo Log 和 Binlog 的区别?
Q2:为什么需要两阶段提交?
保证 Redo Log 和 Binlog 的数据一致性,避免主库和从库数据不一致。Binlog 是崩溃恢复时的“最终仲裁者”,通过两阶段提交确保两份日志要么同时成功、要么同时回滚。
Q3:事务提交后数据就立刻落盘了吗?
不是。事务提交后,Redo Log 和 Binlog 会根据参数配置优先落盘,但数据页本身仍存在 Buffer Pool 内存中,由后台线程异步刷盘落地。宕机时可通过 Redo Log 重做恢复未落地数据。
Q4:什么时候用 InnoDB,什么时候用 MyISAM?
InnoDB:绝大多数 OLTP 业务场景,需要事务、行锁、高并发、数据安全、崩溃恢复的场景。 MyISAM:纯读多写少、静态数据、简单数据仓库场景,目前基本被 InnoDB 全面替代。
Q5:MVCC 的实现原理是什么?
依托 InnoDB 行隐藏字段、Undo Log 版本链、Read View 读视图实现。事务快照读时,通过 Read View 规则遍历版本链,筛选出当前事务可见的数据版本,实现无锁读、事务隔离。
Q6:为什么会产生幻读?如何解决?
RR 隔离级别下,普通行锁仅锁定已有数据,无法锁定空白区间,其他事务可插入新数据,引发幻读。InnoDB 通过间隙锁+临键锁锁定索引间隙,彻底解决幻读问题。
十三、SQL调优金字塔体系(核心调优全集)
13.1 调优核心本质
SQL调优的终极本质只有两点:减少扫描行数、减少回表/临时表/文件排序。所有调优手段均围绕这两个核心展开,以下为完整金字塔分层调优体系(从顶层架构到底层排查,优先级从高到低)。
🏛️ 金字塔第一层:表结构与存储引擎(决定性能上限)
建表阶段的问题是根本性问题,SQL写法优化无法弥补表结构设计缺陷,直接决定数据库性能天花板。
📐 金字塔第二层:索引设计(最高效调优手段)
索引是SQL调优的核心武器,合理的索引设计可直接将查询耗时从数百毫秒降至微秒级,核心是精准命中、避免失效、杜绝回表。
✍️ 金字塔第三层:SQL 写法规范(规避低效写法)
规范的SQL写法可以引导优化器选择最优执行计划,避免人为造成的索引失效、临时表、文件排序等性能问题。
🔬 金字塔第四层:执行计划与故障排查(兜底验证)
通过执行计划和慢查询日志,精准定位慢SQL根因,验证前三层优化效果,是调优的核心排查手段。
13.4.1 EXPLAIN 核心关注三列
13.4.2 慢查询日志核心配置
slow_query_log = ON # 开启慢查询日志
long_query_time = 1 # 执行超过1秒的SQL记录为慢SQL
log_queries_not_using_indexes = ON # 记录所有未走索引的SQL13.4.3 紧急慢SQL处理
SHOW PROCESSLIST; # 查看当前数据库所有线程
KILL 线程ID; # 杀死阻塞、卡死的慢SQL线程📊 终极慢SQL排查决策树
遇到慢SQL严格按照以下流程排查,杜绝盲目优化,精准定位问题:
① 先看 EXPLAIN 执行计划
├── Extra 有 Using temporary/filesort? → 重写SQL,消除排序、临时表
├── type = ALL / key = NULL? → 为WHERE、JOIN字段新增优化索引
└── rows 预估行数极大? → 排查隐式转换、优化WHERE筛选条件
② 再对比扫描行数与返回行数
├── 扫描10万行、返回10行 → 索引过滤性差,调整联合索引顺序/优化SQL
└── 扫描行数与返回行数接近 → SQL性能优秀,无需优化
③ 最后排查数据库整体压力
├── QPS极高 → 引入Redis缓存减轻DB压力
├── 锁等待严重 → 优化长事务、缩小锁范围、提升索引命中率
└── 单表数据千万/亿级 → 冷热分离、分库分表架构优化💡 SQL调优黄金核心法则
永远用 EXPLAIN 说话,拒绝直觉调优,所有优化必须基于执行计划验证。
调优本质=减少I/O开销:覆盖索引减回表、精准索引减扫描、优化SQL减临时表/排序。
SQL优化到极限后,用架构破局:单表优化无效时,通过缓存、分表、冷热分离解决性能瓶颈。
笔记整理于 2026 年 7 月,涵盖MySQL架构、日志、事务、MVCC、锁机制、全套SQL调优体系