深入Mysql(执行流程)

Select执行流程(理解mysql执行流程)

graph TD
    B[连接器] --> C{查询缓存命中?}
    C -->|是| D[返回缓存结果]
    C -->|否| E[解析器]
    E --> F[预处理器]
    F --> G[优化器]
    G --> H[执行器]
    H --> I[存储引擎]
    I --> J[返回结果]
    J --> K[更新查询缓存]

    style D fill:#bbf,stroke:#333
    style J fill:#9f9,stroke:#333

执行过程遵从上图流程

  • mysql分为server层和引擎层,其中连接器到执行器的部分属于server层

连接器

用于管理mysql连接,权限验证。通常我们优先使用长连接,并用连接池hold住以减少因频繁创建连接的损耗。

note:

  • 验证用户名、密码、IP 权限(基于 mysql.user 表)
    • 当建立连接后mysql将不再校验权限,因此中途如果权限发生变更已有的连接将不受影响;
  • mysql的内存对象通常是和连接绑定,因此如果长时间持有连接不释放则可能会导致内存泄漏甚至因oom被操作系统shutdown;
    • 可以定时断开并重连连接;
    • mysql(5.7)以后支持reset连接从而释放内存;
  • mysql的连接如果长时间不使用则会删除自动断开(默认阈值8小时);

缓存(MySQL 8.0已移除)

缓存以key-value键值对形式存在

  • key:sql语句
  • value:数据

场景:

  • 查询缓存
    • 执行 SELECT 语句前,先检查查询缓存是否命中。
    • 如果命中,直接返回缓存结果(跳过后续步骤)。
  • 失效缓存
    • 任何对表的修改(INSERT/UPDATE/DELETE)都会使该表的所有缓存失效。
  • 适用场景
    • 适合读多写少的静态表(如系统配置表)
    • MySQL 8.0 移除原因:缓存命中率低,维护缓存开销大,影响高并发性能。

解析器

对 SQL 语句进行 词法分析 + 语法分析,生成解析树(Parse Tree)

  • 词法分析

    • 将 SQL 拆分成 关键字、表名、列名、运算符 等 Token。

    • 例如

      1
      SELECT id FROM users WHERE age > 18

      会被拆解为:

      • SELECT(关键字)
      • id(列名)
      • FROM(关键字)
      • users(表名)
      • WHERE(关键字)
      • age > 18(条件表达式)
  • 语法分析

    • 检查 SQL 是否符合 MySQL 语法规则(如 SELECT 拼写错误会在此报错)。
    • 生成 解析树(Parse Tree),供优化器使用。

优化器

作用:基于 执行成本(Cost-Based Optimization, CBO) 选择最优执行计划。
详细流程

优化策略:

  • 决定 使用哪个索引(如 age 索引 vs. name 索引)。
  • 决定 表的连接顺序(如 A JOIN B vs. B JOIN A)。
  • 决定 是否使用临时表(如 GROUP BY 优化)。

执行计划生成:

  • 生成

    执行计划(Execution Plan),可通过EXPLAIN查看:

    sql

    1
    EXPLAIN SELECT * FROM users WHERE age > 18;

执行器

调用 存储引擎接口,执行优化器生成的计划,返回结果。

  • 根据具体实现选择MyISAMInnoDB

数据读取:

  • 执行器调用引擎的接口,如:
    • InnoDB:通过 B+树索引全表扫描 查找数据。
    • MyISAM:直接从 .MYD 文件读取数据。

事务支持:

  • InnoDB 支持事务(BEGIN/COMMIT/ROLLBACK)。
  • MyISAM 不支持事务。

锁机制:

  • InnoDB 支持 行锁MyISAM 仅支持 表锁

update执行流程(理解binlog和redolog)

和select基本一致,但有以下不同点

  • 根据update的table来决定失效哪个缓存
  • 会分别写入redoLog和BinLog

RedoLog

由innodb存储引擎实现,是实现系统崩溃回滚的重要实现。

如何使用?

redolog是一个文件组,存储一系列redolog日志,默认2个。它们由两个指针write-pointcheck-point维护,write-point用于标记将来要写的位置,每写一条往后移动一格。check-point同理,当表数据被同步到数据库磁盘文件中后他将往后移动一格,并清除之前的数据。

  • write-point追上check-point,说明redolog写满。会导致阻塞。
  • check-point追上write-point,说明redolog已无内容需要同步。

BinLog

  • 位语server层的log,记录每一次操作,类似redis的AOF机制。
  • 同步支持:从库服务器会读取binlog来同步主库的操作。

redolog区别:

  1. redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 层实现的,所有引擎都可以使用。
  2. redo log 是物理日志,记录的是“在某个数据页上做了什么修改”;binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”。
  3. redo log 是循环写的,空间固定会用完;binlog 是可以追加写入的。“追加写”是指 binlog 文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。

Log流程

  1. 根据用户传入的where条件,从引擎中获取数据;
    • 此过程会遍历B+树,且每次都会先从内存buffer中获取,没有则会去磁盘文件中读取数据并加载到buffer。
  2. 将获取的结果回传给server层,再由执行器对这行数据进行修改;并将修改后的数据通过调用引擎接口保存。
  3. 引擎更新数据到buffer内存,并写入一条redolog记录修改且此次redolog数据行的状态为prepare。
  4. 执行器生成这个操作的binlog。
  5. 执行器调用引擎提交当前事务,将redolog的prepare状态改为commit状态。

深入Mysql(执行流程)
https://andrewjiao.github.io/2023/06/18/mysql/深入Mysql(执行流程)/
作者
Andrew_Jiao
发布于
2023年6月18日
许可协议