Skip to content

MySQL基础架构

MySQL是 C/S(Client端 / Server端) 架构。

架构图

MySQL架构包含 Server层存储引擎层

  • Server 层包含 连接器分析器优化器执行器
  • 存储引擎层包含 引擎层存储层

一、连接器

连接器的作用

  • 跟客户端建立连接。
  • 维持和管理连接。
  • 校验用户和获取用户权限

校验用户

客户端进行连接MySQL的命令如下:

java
mysql -h$ip -P$port -u$user -p

在网络连接 TCP 握手成功之后,连接器会校验用户名和密码。

  • 如果用户名或者密码错误,会直接返回错误提示Access denied for user

获取用户权限

用户名密码认证通过后,连接器会到权限表查询用户拥有的权限,并赋予对应操作权限。

假如连接成功后修改用户权限,也不会影响已经建立连接过的用户。只有断开当前连接重新连接,权限才会生效。

数据库连接池

客户端与数据库建立连接的过程是比较复杂的,流程如下:

  1. TCP建立连接的三次握手。
  2. MySQL认证的认证校验。
  3. 真正的SQL执行。
  4. MySQL的关闭。
  5. TCP的四次挥手关闭连接。

数据库连接池能够维护一定的数据库长连接,方便客户端复用,当客户端需要连接数据库时,从连接池获取连接,用完归还即可。无需关心数据库连接池是如何管理这些连接的。

在使用连接池后,除了首次需要进行 MySQL连接的初始化,后续使用只需要关注 执行SQL 这部分的开销。

常见的数据库连接池有:

  • Druid
  • C3p0

池化思想

一般是对象的池化。核心思想是空间换时间

使用预先创建好的对象来减少频繁创建对象的损失,重复利用对象,同时还能够对对象统一管理。

比如:线程池数据库连接池字符串常量池

SQL接口

SQL语句的入口,接受用户的SQL命令,支持接受 DMS,DDL语句,还支持视图、存储过程,并将最终结果返回给用户。

二、查询缓存

在连接器建立连接之后,通过SQL接口接入的SQL语句,若执行的是 select 语句,则连接器会先查询缓存。

  • 查询缓存命中的话,会 判断用户是否有操作表的权限,符合权限会直接返回结果。
  • 查询未命中,会继续后面的执行阶段。

缓存的原理

之前查询的结果会以 K-V 结构存储在缓存中,其中 K 为执行的SQL,V为查询的结果。

当数据表记录更新删除的时候,要同步修改缓存中的数据。

查询缓存的弊端

  1. 查询缓存的 K 需要保证 SQL语句保持一致才会利用到缓存,这也导致查询缓存的场景有局限性。

  2. 若更新删除频繁,查询缓存的利用率会更低。

    因为更新删除数据表后,该表在缓存中的记录要被全部删除。可能存在数据存入缓存还未利用,便被更新操作删除了。

查询缓存适用于不会频繁变动的数据表,比如配置信息表。

手动使用查询缓存

select 语句中,使用关键字 SQL_CACHE 可以手动指定查询缓存。

java
select SQL_CACHE * from class where id =1

MySQL8.0 删除了 查询缓存 这部分功能。

三、分析器

分析器会解析传入的 SQL语句,进行语法分析。

词法分析

MySQL通过语法分析,能够知道 SQL 语句需要执行的功能。

解析 SQL 语句中的关键字,比如 SELECT 关键字,表名等。

语法分析

语法分析的作用是 校验 SQL 的合法性

若 SQL 语句不满足语法规定,会提示 语法错误

java
mysql> elect * from t where ID=1;ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'elect * from t where ID=1' at line 1

语法规定包括 表名字段名称的校验,还有参数等的校验。

四、查询优化器

SQL 语句在被执行之前,会被查询优化器进行优化。

优化器在以下情况下会被使用:

  1. 操作的表包含多个索引。

    优化器会选择合适的索引。

  2. SQL 语句包含连接(JOIN)查询。

    java
    select * from A join B using(ID) where A.c = 10 and B.d=20

    比如先查询 A 表,c=20的记录,再根据 ID 查询 B 表,d=20的记录。假如反过来先查询 B 表,再根据 ID 查询 A 表。

    虽然查询结果一致,但是前后效率是不一致的。

    优化器会选择先执行哪部分效率会更高。


五、执行器

分析器使 MySQL 知道了 SQL语句要做什么,通过优化器对SQL 进行了优化。

最终需要执行器进行 SQL 执行。


权限校验

在执行 SQL 语句之前,执行器会对 SQL 语句中涉及到的表进行 权限校验

  1. 如果没有操作表的权限,会提示权限不足。
java
mysql> select * from T where ID=10;ERROR 1142 (42000): SELECT command denied to user 'b'@'localhost' for table 'T'
  1. 如果权限校验通过,会进行 SQL 执行。

执行器的执行流程

sql
select * from Test where ID=10;

执行器会获取 SQL 语句中的数据表 Test 定义的引擎(InnoDB),再根据引擎的定义接口执行语句。

比如没有索引的情况,执行流程如下:

  1. 调用 InnoDB引擎接口,获取 Test表的第一行,判断 ID = 10。
    • 若不是则跳过,若是则将结果存到结果集中。
  2. 调用引擎接口取下一行。重复第一步的逻辑,直到读到表的最后一行。
  3. 将结果集中所有满足条件的记录返回给客户端。
  4. 将 SQL语句与搜索结果以 K-V形式存入查询缓存。

思考问题

如果表 T 中没有字段 k,而你执行了这个语句 select * from T where k=1 , 那肯定是会报“不存在这个列”的错误: “Unknown column ‘k’ in ‘where clause’”。你觉得这个错误是在我们上面提到的哪个阶段报出来的呢?

在分析器的语法分析阶段报出来。