MySQL基础架构
大体来说,==MySQL可以分为Server层和存储引擎层两部分==。
==Server层包括连接器、查询缓存、分析器、优化器、执行器==等,涵盖MySQL的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等。
而==存储引擎层负责数据的存储和提取。其架构模式是插件式的==,支持InnoDB、MyISAM、Memory等多个存储引擎。现在最常用的存储引擎是InnoDB,它从MySQL 5.5.5版本开始成为了默认存储引擎。
(什么叫插件式?就是说==存储引擎是表级别==的,你可以对每张表选择不同的存储引擎)
连接器
连接器是 MySQL 中负责与客户端建立连接的组件。它的主要功能包括:
- 建立连接:接收客户端的连接请求,验证用户名和密码。
- 获取权限:一旦连接成功,连接器会查询权限表,确定用户的权限范围。
- 管理连接:如果客户端一段时间没有动作,连接器会根据配置参数
wait_timeout
断开空闲连接。
一个用户建立连接后,他的权限是在建立连接的时刻确定的。连接建立后,若用户的权限在此期间被修改,当前连接的权限并不会受到影响,只有新连接才会应用新的权限。(这个应该做实验验证一下)
在查询 show processlist
中可以看到空闲连接,显示为 Sleep
。当连接超时后,会自动断开,客户端再次发送请求时会收到 “Lost connection” 的错误提示。
查询缓存(谨慎使用)
查询缓存是 MySQL 在执行 SELECT
语句时的一个优化机制,旨在通过缓存查询结果提高查询效率。其工作方式是:
- 当一条 SQL 查询请求发出时,MySQL 首先会检查查询缓存中是否存在该查询结果。如果存在,直接返回缓存中的结果,避免复杂的执行过程。
- 如果没有命中缓存,则执行查询并将结果缓存起来,供后续相同查询使用。
然而,查询缓存有一个严重的问题:频繁失效。一旦有对表的更新操作,涉及该表的所有缓存都会失效。因此,在数据更新频繁的情况下,查询缓存命中率低,甚至可能拖累系统性能。
MySQL 8.0 版本中,查询缓存已经被完全移除。因此,建议在 MySQL 5.7 及以下版本中,谨慎使用查询缓存,只在特定静态数据表上开启。
分析器
当查询语句通过连接器进入 MySQL 后,首先由分析器处理。分析器的作用是解析 SQL 语句,理解用户的查询意图。它分为两个阶段:
- 词法分析:将用户输入的字符串拆分成不同的部分,识别出 SQL 关键字、表名、列名等。
- 语法分析:根据 MySQL 的语法规则检查 SQL 语句的正确性。如果有语法错误,会返回相应的错误信息。
比如,如果用户少写了一个字母导致 SQL 语句不合法,分析器就会抛出类似 “You have an error in your SQL syntax” 的错误。
顺便复习一下编译原理的编译过程:
编译阶段 详细说明 1.词法分析 从源代码中读取字符流,并根据语言的词法规则识别出最小的语法成分(Token),如关键字、标识符、常量、运算符等。同时去除空格、注释等。 2. 语法分析 根据语言的语法规则,将词法分析生成的 Token 序列组织成语法树或抽象语法树(AST)。确保输入代码的结构符合语言定义的句法。 3. 语义分析 检查语法树是否符合语言的语义规则。例如:变量在使用前是否声明,数据类型是否匹配,操作符和操作数是否兼容。此阶段可能会生成符号表。 4. 中间代码生成 将语法分析后的代码转换为与机器无关的中间代码形式,便于后续的优化和代码生成。 中间代码形式通常比源代码更接近目标机器代码,但保持与具体硬件平台无关。 5. 优化 对中间代码进行优化,使生成的目标代码运行得更快或占用更少的资源。优化可以是局部的(局部变量、循环优化)或全局的(跨函数优化、常量传播、死代码消除) 6. 目标代码生成 目标代码生成器将中间代码转换为特定机器架构的机器代码或汇编代码。此时会为每个符号分配存储位置、寄存器分配等。 7. 汇编和链接 汇编器将生成的汇编代码转换为机器可执行的目标代码。链接器负责将不同的目标模块和库进行链接,生成完整的可执行程序。
优化器
优化器的任务是在知道用户要执行的查询后,决定如何高效地执行该查询。例如,在一条 SQL 查询中,可能有多个索引供选择,优化器决定使用哪个索引;在多表关联查询(JOIN
)中,优化器会决定表的连接顺序。
优化器不会改变查询的结果,只会优化查询的执行路径,保证更高效的执行。例如,在多表 JOIN
时,优化器会选择最优的表扫描顺序,从而减少查询的时间和资源消耗。
执行器
执行器是 MySQL 执行查询的最后一步。执行器负责根据优化器生成的执行计划,逐步执行查询。具体步骤如下:
- 权限检查:首先,执行器会检查用户对相关表是否有权限。如果没有权限,查询会立即返回权限不足的错误。
- 调用存储引擎接口:根据查询的表,执行器会调用对应存储引擎(如 InnoDB)的接口来执行具体的操作。例如,如果是一个无索引的表,执行器会逐行扫描表的数据,找到符合条件的记录。
执行器根据优化器的方案,依次处理每一个表中的数据并返回最终的结果集。执行器会利用存储引擎提供的接口来获取数据,处理每一行并组成查询结果返回给客户端。
问题:"不存在的列"报错来自哪个阶段?
如果表T中没有字段k,而你执行了这个语句 select * from T where k=1,那肯定是会报“不存在这个列”的错误: “Unknown column ‘k’ in ‘where clause’”。这个错误是在哪个阶段报出来的呢?
答:在分析器阶段报出来的。分析器会根据数据库表的定义,检查 SQL 语句中的字段是否存在。如果表
T
中不存在字段k
,分析器在这个阶段就会发现。