跳到主要内容

mysql

mysql

一条sql经历了什么

主要分为 Server 层(负责逻辑)和 存储引擎层(负责物理读写)

第一阶段:连接管理 (Connection Handling)

当客户端(如 Go 程序、Navicat)发起请求时,服务端首先由连接器接待。

  1. 三次握手:建立 TCP 连接。
  2. 身份验证:校验用户名和密码。
  3. 权限读取:验证通过后,连接器会到权限表中查询该用户拥有的权限,并保存在当前连接的上下文中。
    • 注意: 只要连接不断开,即使管理员中途修改了权限,当前连接也感知不到,必须重新连接。

第二阶段:解析与预处理 (Parser & Preprocessor)

连接建立后,SQL 进入“语法分析”阶段。

  1. 词法分析 (Lexical Analysis):MySQL 会识别出 SQL 里的关键字。比如 SELECT 识别为查询,FROM 后面是表名,WHERE 后面是过滤条件。
  2. 语法分析 (Syntax Analysis):根据 SQL 语法规则,判断你写的 SQL 是否合规(比如有没有少个逗号)。如果没问题,会生成一棵 解析树 (Parse Tree)
  3. 预处理器 (Preprocessor)
    • 检查表名或字段名是否存在。
    • 检查是否有对应字段的查询权限。
    • 将别名还原等。

第三阶段:查询优化 (Optimizer)

这是 MySQL 最核心的“大脑”部分。

  • 执行计划制定:优化器会根据成本 (Cost) 模型,决定:
    • 如果有多个索引,用哪个索引?
    • 多表关联时,先驱动哪张表(连接顺序)?
  • 重写 SQL:将复杂的逻辑简化,或者进行“谓词下推”等优化。
  • 最终产物:生成一个执行计划。你可以通过 EXPLAIN 命令看到这个计划。

第四阶段:执行器 (Executor)

拿到执行计划后,真正的“搬砖”工作开始了。

  1. 权限校验:开始执行前再次校验是否对该表有执行具体操作的权限(虽然预处理查过,但执行器是最终把关人)。
  2. 调用存储引擎接口:执行器并不直接读文件,它通过标准的 API 接口去问存储引擎(如 InnoDB)拿数据。
    • 例子:执行器问:“给我 users 表第一行。”
    • InnoDB 答:“给,这是数据。”
    • 执行器问:“这行 id 是 1 吗?如果是,我就存到结果集;如果不是,跳过。再给我下一行。”

第五阶段:存储引擎层 (Storage Engine)

这是真正和磁盘打交道的地方(以 InnoDB 为例)。

  1. Buffer Pool:首先看内存(Buffer Pool)里有没有数据,有则直接返回。
  2. 磁盘 IO:内存没有,则从磁盘加载数据页。
  3. 返回数据:将结果返回给执行器。

特别注意:查询缓存 (Query Cache) 如果你看的是旧教材,可能会提到“查询缓存”。

MySQL 8.0 已经彻底删除了查询缓存功能。因为它失效太快(只要表有更新,缓存全灭),在现代高并发场景下弊大于利。

MySQL 死锁检测算法 & 选择主动牺牲的事务

MySQL 解决死锁的核心是 基于等待图(Wait-for Graph, WFG)的死锁检测算法,而选择主动牺牲(回滚)的事务遵循 最小回滚代价原则,整个流程由 InnoDB 引擎自动完成,无需人工干预。

一、死锁检测核心算法:等待图(WFG)检测

InnoDB 是基于行锁实现事务并发控制的,死锁的本质是多个事务间形成了循环等待锁资源的闭环。其检测流程如下: