mysql执行SQL的存储引擎层流程_mysql存储引擎访问解析

0次阅读

存储引擎层响应 Server 层指令执行底层操作:InnoDB 按 B + 树逐层加载页查找记录、INSERT 涉及页分裂与锁管理、SHOW ENGINE STATUS 不显示隐式锁等待链。

mysql 执行 SQL 的存储引擎层流程_mysql 存储引擎访问解析

MySQL 执行 SQL 时,存储引擎层到底做了什么

SQL 到达 MySQL Server 层后,经过解析、优化生成执行计划,最终由 handler 接口调用具体存储引擎(如 InnoDB、MyISAM)完成数据访问。存储引擎层不负责 SQL 语法、事务隔离级别或查询重写,只响应 Server 层发来的「读哪行」「写哪页」「加什么锁」等底层操作指令。

InnoDB 的 B+ 树查找路径如何对应到一次 SELECT

SELECT * FROM t WHERE id = 100 走主键索引时,InnoDB 的实际动作是:

  • dict_table_t 获取表元数据,确认聚簇索引根页位置(通常在 ibdata1 文件固定偏移处)
  • 按 B+ 树层级逐层读取:先读根页 → 解析页内 slot 数组定位子页 → 加载子页到 buf_pool → 继续下钻,直到叶子页
  • 在叶子页中线性扫描或二分查找匹配 id = 100rec_t 记录
  • 若开启 READ COMMITTED 或更高隔离级别,还需调用 row_sel_get_clust_rec_for_mysql 构造可见版本

注意:即使命中索引,也 ** 不是直接跳转物理地址 **——B+ 树所有节点都需通过页号(page_no)经 buffer pool 管理器加载,磁盘 I/O 开销藏在这里。

INSERT 触发的存储引擎层关键动作

InnoDB 对 INSERT 的处理远不止“写一行”,尤其在高并发下:

  • 先尝试在当前叶子页插入;若空间不足,触发 btr_page_split 分裂,可能引发父节点更新甚至根页升级
  • 自增主键会调用 dict_table_get_next_autoinc 获取值,该操作在内存中加 autoinc_mutex 锁(非表级锁,但仍是瓶颈点)
  • 插入前必须获取 LOCK_X 行锁(记录锁或间隙锁),锁信息存于 lock_sys->rec_hash 哈希表,而非记录本身
  • 实际写入的是 undo log + redo log + buffer pool 中的 page,磁盘落盘由 flush_listcheckpoint 异步控制

为什么 SHOW ENGINE INNODB STATUS 看不到真实的行锁等待链

SHOW ENGINE INNODB STATUS 输出的 TRANSACTIONS 部分只展示 ** 当前持有锁和显式等待锁的事务 **,但真实场景中常存在隐式等待链(例如事务 A 持有锁,事务 B 等待 A,事务 C 又等待 B)。这是因为:

  • InnoDB 的锁等待检测仅在 lock_wait_check_pending 中做单层检查,不递归遍历等待图
  • 死锁检测(deadlock_check)才真正构建等待图,但结果只用于回滚,不暴露给 STATUS
  • 要定位深层阻塞,必须结合 information_schema.INNODB_TRXINNODB_LOCK_WAITSINNODB_LOCKS(5.7+ 已废弃,8.0 改用 performance_schema.data_locks)关联分析

真正棘手的锁问题,从来不在 STATUS 的第一眼输出里。

星耀云
版权声明:本站原创文章,由 星耀云 2026-03-14发表,共计1287字。
转载说明:转载本网站任何内容,请按照转载方式正确书写本站原文地址。本站提供的一切软件、教程和内容信息仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。
text=ZqhQzanResources