mysql SQL执行流程是什么_mysql执行过程解析

2次阅读

连接器先校验身份再查权限表,按user→db→tables_priv→columns_priv逐级检查;解析器阶段报错说明语句未通过词法和语法分析;优化器基于成本估算选索引,FORCE INDEX非绝对生效;mysql 8.0已彻底移除查询缓存。

mysql SQL执行流程是什么_mysql执行过程解析

连接器先校验身份,再查权限表

你执行 mysql -u root -p 后输入密码,连接器干的不是“连上就完事”,而是立刻查 mysql.user 表确认账号是否存在、密码哈希是否匹配;通过后,再按 user → db → tables_priv → columns_priv 顺序逐级查权限。哪怕你只查一张表的某个字段,只要 columns_priv 里没开对应列的 select 权限,就会报 Error 1142 (42000): SELECT command denied to user,而不是语法错误。

常见踩坑点:

  • SHOW PROCESSLIST 能看到当前所有连接的 IdUser,但看不到具体权限——权限是会话级缓存的,改了 mysql 库的权限表后,必须执行 FLUSH PRIVILEGES 或让客户端重连才生效
  • wait_timeout 默认 8 小时,长连接空闲太久会被自动断开,应用层若没做重连逻辑,就会突然报 MySQL server has gone away
  • 权限验证失败时,错误信息里带 @'host'(比如 'root'@'192.168.1.100'),说明 MySQL 是按「用户名+来源 IP」组合鉴权的,不是单看用户名

解析器报错 = 语句根本没进优化器

当你写错 SELECT * FROM users WHERE id = 123;SELCT * FROM users WHERE id = 123;,或者查一个不存在的列 SELECT phone FROM users;,错误发生在解析器阶段——它做完词法分析(拆出关键字、标识符)和语法分析(检查结构是否符合 SELECT ... FROM ... WHERE ... 规则)后直接报错,根本不会走到优化器或执行器。

这意味着:

  • EXPLAIN 对这种语句无效,执行就报错,没法看执行计划
  • 语法检查顺序严格:SELECT → FROM → JOIN → ON → WHERE → GROUP BY → HAVING → union → ORDER BY → LIMIT,漏写 FROM 或把 WHERE 写在 GROUP BY 前面,都会被解析器拦下
  • 大小写和空格敏感:在 MySQL 5.7 及以前,select * from tSELECT * FROM t 是两个不同缓存 key(虽然 8.0 已删缓存,但解析器仍按字面值比对)

优化器选索引不认你写的 FORCE INDEX?正常

你加了 FORCE INDEX (idx_created_at),但 EXPLAIN 显示还是走全表扫描?不是 MySQL 忽略你,而是优化器在 ANALYZE TABLE 统计信息基础上做了成本估算:如果 created_at 索引选择性差(比如只有 3 个不同值)、表又小(Rows 显示才几百行),它判断走索引回表反而比直接扫更快。

实操建议:

  • SHOW TABLE STATUS LIKE 'orders'RowsData_length,再用 SELECT count(DISTINCT status) / COUNT(*) FROM orders 算选择性,低于 0.01 就别指望它用这个字段索引
  • FORCE INDEX 是绕过优化器的“硬指令”,但数据量突增后可能从加速变拖慢,线上慎用
  • 真正可控的是建好复合索引:比如 WHERE status = ? ORDER BY created_at DESC,优先建 (status, created_at) 而非单列索引

MySQL 8.0 起,查询缓存已彻底消失

别再查 query_cache_size 或设 query_cache_type = 1——MySQL 8.0 把整个查询缓存模块(包括内存管理、失效逻辑、所有相关变量)全删了。你升级到 8.0 后如果还依赖缓存,要么换应用层缓存(redis),要么靠 InnoDB 缓冲池(innodb_buffer_pool_size)扛热数据。

为什么删?因为:

  • 缓存 key 是 SQL 字符串全匹配,SELECT * FROM tSELECT * FROM t(多两个空格)就是两个缓存项
  • 一张表任何 INSERT/UPDATE/delete,所有涉及该表的缓存全部失效,写多读少场景下命中率趋近于 0
  • 线程争抢缓存锁,高并发时反而成为瓶颈

现在真正的“缓存”只剩两层:InnoDB 的数据页缓存(由 innodb_buffer_pool_size 控制),和操作系统的 page cache——它们不认 SQL,只认磁盘块,更底层也更稳定。

text=ZqhQzanResources