SQL 语句在 MySQL 中的执行过程
SQL 在 MySQL 中的执行过程可以分为以下 6 个步骤:
1️⃣ 客户端请求 2️⃣ 连接管理 3️⃣ 查询缓存(MySQL 8.0 以后移除) 4️⃣ SQL 解析、优化 5️⃣ 执行计划 6️⃣ 存储引擎获取数据 7️⃣ 返回结果
1️⃣ 客户端请求
你在 MySQL 客户端(如 MySQL Workbench、Navicat、JDBC)或应用程序中执行 SQL 语句:
SELECT name FROM users WHERE id = 1001;
- MySQL 服务器 会监听 TCP 3306 端口,接收客户端的 SQL 请求。
2️⃣ 连接管理
📌 MySQL 需要先建立连接,验证身份和权限。
- 连接管理器 检查用户是否有权限访问该数据库。
- MySQL 使用身份认证(用户名 + 密码)验证连接。
- 连接池机制 允许复用连接,提高性能。
🔹 示例: 如果你的 MySQL 账户没有权限查询 users
表,就会报错:
ERROR 1045 (28000): Access denied for user 'test_user'@'localhost' (using password: YES)
3️⃣ 查询缓存(MySQL 8.0 已移除)
📌 查询缓存(Query Cache) 在 MySQL 8.0 以前 存在,作用是缓存 SQL 结果,如果相同查询已经执行过,MySQL 可以直接返回结果,提高查询效率。
🚨 MySQL 8.0 及以上版本已移除查询缓存,因为查询缓存在高并发场景下会导致锁争用,影响性能。
4️⃣ SQL 解析 & 语法检查
📌 MySQL 解析 SQL 语句,检查语法是否正确:
- 词法分析(Lexing):将 SQL 拆分成关键字、表名、字段等。
- 语法分析(Parsing):使用 MySQL 解析器(Parser) 检查 SQL 语法是否正确。
- 生成解析树(Parse Tree):如果 SQL 语法无误,生成 解析树,表示 SQL 结构。
5️⃣ 查询优化
📌 MySQL 优化器(Optimizer) 生成最优执行计划:
- 是否使用索引?
- 是否进行表扫描(Full Table Scan)?
- 是否使用多表 JOIN 优化?
- 是否使用排序、分组优化?
- 是否可以合并查询?
6️⃣ 执行计划
📌 MySQL 根据优化器的执行计划,调用存储引擎获取数据。
- 如果 SQL 走索引(如 B+ 树索引),会直接通过索引查找数据,避免全表扫描。
- 如果没有索引,MySQL 只能进行“全表扫描”,效率较低。
7️⃣ 存储引擎获取数据
📌 MySQL 的存储引擎(InnoDB、MyISAM 等)负责数据的实际存取。
- 如果查询使用 InnoDB(默认存储引擎)
- 先在 Buffer Pool(内存) 查找数据。
- 如果缓存中没有,去 磁盘 读取数据页到 Buffer Pool,再返回结果。
- 更新查询会先修改 Buffer Pool,再异步刷新到磁盘(WAL 机制)。
- 如果查询使用 MyISAM
- 直接从磁盘读取数据,查询速度相对较慢。
8️⃣ 返回查询结果
📌 MySQL 最后将查询结果返回给客户端:
- MySQL 以数据流的方式返回结果,不需要一次性加载所有数据到内存。
- 如果是大数据查询,可以使用 LIMIT 进行分页,减少内存消耗:
🚀 总结
步骤 | 描述 |
---|---|
1️⃣ 客户端请求 | MySQL 接收 SQL 请求 |
2️⃣ 连接管理 | 验证用户权限 |
3️⃣ 查询缓存(MySQL 8.0 移除) | 直接返回缓存数据(如果存在) |
4️⃣ SQL 解析 | 词法分析、语法分析、生成解析树 |
5️⃣ 查询优化 | 选择最优索引,生成执行计划 |
6️⃣ 执行计划 | 根据存储引擎(InnoDB / MyISAM)查询数据 |
7️⃣ 存储引擎获取数据 | InnoDB 走 B+ 树索引查找数据 |
8️⃣ 返回结果 | MySQL 返回数据到客户端 |