MySQL 架构与SQL执行全流程深度解析

一、MySQL怎么学:体系化学习路线

学习MySQL,建议按以下三个层次逐步深入:

1. 前置基础(必须掌握)

  • 全面理解MySQL架构(本篇重点)

  • 索引底层数据结构与算法

  • Explain详解与索引最佳实践

  • 索引优化实战(一、二)

2. 进阶理解(深入内核)

  • 事务隔离级别与锁机制

  • MVCC与BufferPool缓存机制

  • 各种日志实现机制(redo log、binlog、undo log)

  • MySQL全局优化与MySQL 8.0新特性

3. 集群架构(高可用扩展)

  • MySQL 8集群架构(一、二)

二、一条SQL查询语句是如何执行的?

我们先来看一个最简单的查询:

复制代码
SELECT * FROM user WHERE id = 10;

它的执行流程如下图所示,分为Server层和存储引擎层两大模块:

复制代码
客户端 → 连接器 → 查询缓存 → 分析器 → 优化器 → 执行器 → 存储引擎

2.1 连接器

负责客户端连接管理、权限验证等。常用命令:

复制代码
mysql -h$ip -P$port -u$user -p

长连接 vs 短连接:

  • 长连接:连接后持续使用,减少重复连接开销,但可能导致内存泄漏

  • 短连接:每次查询完断开,下次重连,适合低频访问

连接池建议:

生产环境推荐使用连接池(如HikariCP、Druid),避免频繁创建连接,提升并发性能。

2.2 查询缓存(MySQL 8.0已移除)

在MySQL 5.7中,查询缓存用于缓存SELECT语句结果,key为SQL语句,value为结果集。

但在高并发更新场景下,缓存命中率极低,且维护成本高,因此在MySQL 8.0中已被彻底移除

2.3 分析器

如果没有命中缓存,SQL语句会进入分析器,分为两步:

  1. 词法分析:识别SQL关键字、表名、列名等

  2. 语法分析:判断SQL是否符合语法规则

如果语法错误,会报错:

复制代码
ERROR 1064 (42000): You have an error in your SQL syntax...

思考题:如果执行 SELECT * FROM T WHERE k=1,但表中没有k列,是在哪个阶段报错?
答案:分析器阶段。

2.4 优化器

优化器负责选择最优执行计划,例如:

  • 选择哪个索引

  • 多表JOIN时决定连接顺序

示例:

复制代码
SELECT * FROM t1 JOIN t2 USING(ID) WHERE t1.c=10 AND t2.d=20;

优化器会评估两种方案,选择扫描行数少、成本低的方案。

2.5 执行器

执行器负责调用存储引擎接口执行查询,并在执行前进行权限校验。

即使命中缓存,也会在返回结果前进行权限验证。


三、一条SQL更新语句是如何执行的?

更新语句同样会走查询的流程,但多了两个关键日志模块:

  • redo log(重做日志):InnoDB引擎特有,物理日志,保证crash-safe

  • binlog(归档日志):Server层实现,逻辑日志,用于数据归档与复制

3.1 redo log(粉板记账法)

InnoDB使用WAL技术(Write-Ahead Logging) ,先写日志,再写磁盘。

redo log是循环写入的,固定大小(如4个文件,每个1GB),通过write pos和checkpoint指针控制写入与擦除。

3.2 binlog(归档账本)

binlog是逻辑日志,记录的是SQL语句的原始逻辑,支持追加写入,用于数据恢复和主从复制。

3.3 更新流程示例

以更新语句为例:

复制代码
UPDATE T SET c=c+1 WHERE ID=2;

执行步骤:

  1. 执行器找引擎取ID=2这一行(若不在内存则从磁盘读入)

  2. 执行器将c值加1,调用引擎写入新行

  3. 引擎更新内存,并写入redo log(prepare状态)

  4. 执行器写binlog

  5. 执行器调用引擎提交事务,redo log改为commit状态


四、两阶段提交(内部XA)

为了保证redo log和binlog的逻辑一致性,MySQL使用两阶段提交

4.1 如果不使用两阶段提交,会出现什么问题?

  • 先写redo log后写binlog:redo log中事务已提交,binlog丢失,从库恢复时数据不一致

  • 先写binlog后写redo log:binlog有记录,redo log未提交,主库恢复后事务丢失,从库多出一条数据

4.2 崩溃恢复逻辑

  1. 如果redo log有commit标识,直接提交

  2. 如果只有prepare,则检查对应binlog是否完整:

    • binlog完整 → 提交事务

    • binlog不完整 → 回滚事务

4.3 redo log与binlog的关联

通过XID字段关联。崩溃恢复时,按顺序扫描redo log:

  • 有prepare + commit → 提交

  • 只有prepare → 去binlog中查找对应XID的事务


五、Java开发者需要注意的几点

5.1 连接管理

推荐使用连接池,避免频繁创建连接,注意设置合理的wait_timeout

5.2 事务控制

理解innodb_flush_log_at_trx_commitsync_binlog参数对数据一致性的影响。

5.3 数据恢复

定期备份 + binlog归档,可实现任意时间点的数据恢复。误删数据后恢复流程:

  1. 取最近一次全量备份

  2. 重放binlog到误删前一刻


六、总结

MySQL的架构清晰分为Server层和存储引擎层,SQL执行过程依次经过连接、缓存、分析、优化、执行等阶段。更新语句额外依赖redo log和binlog两大日志系统,通过两阶段提交保证数据一致性。

相关推荐
·云扬·9 小时前
【实操教程】Excel文件转CSV并导入MySQL的完整步骤
android·mysql·excel
一条咸鱼_SaltyFish9 小时前
[Day16] Bug 排查记录:若依框架二次开发中的经验与教训 contract-security-ruoyi
java·开发语言·经验分享·微服务·架构·bug·开源软件
幻云20109 小时前
Next.js 之道:从全栈思维到架构实战
开发语言·javascript·架构
程序猿202310 小时前
MySQL的逻辑存储结构
java·数据库·mysql
没有bug.的程序员10 小时前
Kubernetes 与微服务的融合架构:调度、弹性、健康检查深度协同
jvm·微服务·云原生·架构·kubernetes·健康检查·弹性伸缩
C+++Python10 小时前
Flume的核心概念和架构
大数据·架构·flume
霖霖总总12 小时前
[小技巧19]MySQL 权限管理全指南:用户、角色、授权与安全实践
数据库·mysql·安全
Jing_jing_X16 小时前
AI分析不同阶层思维 二:Spring 的事务在什么情况下会失效?
java·spring·架构·提升·薪资
麦聪聊数据18 小时前
MySQL并发与锁:从“防止超卖”到排查“死锁”
数据库·sql·mysql