> For the complete documentation index, see [llms.txt](https://yunzhao.gitbook.io/notes/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://yunzhao.gitbook.io/notes/database/mysql/architecture.md).

# Architecture

MySQL 由 **Server 层**和**存储引擎**组成。

![](https://3232244687-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LYZow-MmROshIrkwdtE%2F-Lc_Y5EotFM5UUYvxOvT%2F-Lc_YL83azq5ZS57RsFX%2Fimage.png?alt=media\&token=4f07a662-d4f1-4054-bfcc-b81f43df1507)

## Server层

涵盖 MySQL 的大多数核心功能，以及所有的内置函数（如日期、时间、数学、加密等），所有跨存储引擎的功能都在这一层实现，如存储过程、触发器、视图等。

### 连接器

负责与客户端建立连接、获取权限、维持和管理连接。

```bash
mysql -h $ip -P $port -u $user -p
```

输入正确的密码后，连接器到权限表查询**权限**。之后，这个链接的所有权限判断都依赖于此次读到的权限。也就是说，用户建立连接后，即使管理员对这个用户权限做了修改，不会立即生效，只有用户重新建立连接才会生效。

连接后，若没有后续请求，则连接处于空间状态，`show processlist`，Command 列为 sleep表示空闲。默认空闲8小时（参数`wait_timeout`控制）后，断开链接。

MySQL 执行过程中使用的内存是由连接对象管理的，这些资源在断开连接时才会释放，所以**长连接**累积下来，可能导致内存占用太大，被系统强行杀掉，MySQL就异常重启了。

1. 可以定期断开长连接。
2. 5.7后，可以执行`mysql_reset_connection`来重新初始化连接资源，不会重连和做权限验证。

### 查询缓存

缓存的 **key 是查询语句**，**value 是查询结果**。若查询命中缓存，则直接返回结果。若没命中，则执行后续阶段，执行结果会存入缓存中。

{% hint style="warning" %}
MySQL 8.0删除了整块查询缓存的功能。
{% endhint %}

建议**不用缓存**，原因是缓存失效非常频繁，只要对一个表有更新，整个表的缓存都会清空。除非业务是静态表，基本不更新，比如系统配置表。

参数`query_cache_type`设置成 DEMAND 后，SQL 默认不使用缓存，可以用 SQL\_CACHE 显示指定需要缓存，如：

```
select SQL_CACHE * from T where ID=10；
```

### 分析器

负责对 SQL 做解析。

* **词法分析：**&#x8BC6;别出由字符串和空格组成的 SQL 语句中的字符串。比如`select * from T where ID=10`，会把 T 识别成表名，ID 识别成列。
* **语法分析：**&#x5224;断 SQL 语句是否合法，若不合法，会收到 “You have an error in your SQL” 的错误。

### 优化器

* 决定是否使用或者使用哪个索引。
* 决定多表关联（join）时各个表的连接顺序。

### 执行器

首先判断是否有权限（之前若缓存命中，也会执行权限验证）。

根据表的引擎定义，使用对应引擎的接口。还是以`select * from T where ID=10`为例，假设 ID **没有索引**，步骤如下：

1. 在InnoDB引擎接口获取表第一行，判断ID是否为10，不是则跳过，是则加入结果集。
2. 调用“下一行”接口。
3. 执行器将结果集返回给客户端。

**对于有索引**的表，流程类似，第一调用“**取满足条件的第一行**”，之后循环调用“**满足条件的下一行**”。这些接口都是引擎中定义好的。

在慢查询日志中有`row_examined`字段，表示执行过程扫描了多少行，是在每次调用引擎获取数据行时累加的。

有些场景，执行器调用一次，引擎扫描多行，因此引擎扫描行数与`row_examined`并不完全相同。

## 存储引擎

* 负责数据的存储和提取。
* **插件式**架构，支持 InnoDB、MyISAM、Memory 等，从 5.5.8 版本开始默认为 InnoDB。
* 可以通过 create table 的时候指定 engine 来选择存储引擎。
* 不同的存储引擎公用一个 Server 层。

常见的存储引擎特性：

* InnoDB：5.5.8 之后的默认引擎，特点是支持事务、行级锁、外键等；
* MyISAM：5.5.8 之前的默认引擎，不支持事务，不支持外键，特点是速度快、占用资源少；
* Memory：会丢失数据，速度更快；
* NDB：也叫 NDB Cluster，用于 MySQL Cluster 的分布式集群；
* Archive：很好的压缩机制，用于文件归档。

{% hint style="info" %}
MySQL 的每个表可以采用不同的存储引擎。
{% endhint %}
