MySQL 执行流程
客户端 ---TCP连接---> 连接器 -> 查询缓存 -> 词法分析 -> 语法分析 -> 语法树 -> 预处理器 -> 优化器 -> 执行计划 -> 执行器 -> 存储引擎

连接器
与 mysql 建立连接的过程?
通过
mysql -h$ip -u$user -p连接 MySQL 服务。连接的过程需要先经过 TCP 三次握手。因为 MySQL 是基于 TCP 协议进行传输的。 完成 TCP 连接的建立后,连接器开始验证用户名和密码是否正确,如果用户名和密码没有问题,连接器会获取该用户的权限,然后保存起来, 后续在该用户在连接的任何操作,都会基于连接开始时读到的权限进行权限逻辑的判断。
这就解释了,为什么修改用户的权限之后,没有立即生效,因为权限的判断是基于创建连接时读取到的权限。如果想让权限立即生效,需要执行 flush privileges.
或者重新登录即可获取到最新的权限。
空闲连接会一直占用着吗?
通过
show processlist;可以查看哪些连接处于空闲状态。空闲连接达到一定的时间之后会自动断开。通过show variables like '%wait_timeout%';来查看这个最大空闲时长。并且,这个连接断开时,客户端并不会第一时间直到,只有等待客户端发起下一次请求时,才会收到连接断开的报错。
MySQL 的连接数有限制吗?
有,通过
show variables like 'max_connections';命令查看最大连接数。
mysql 的长连接和短连接
- 短连接
- 连接 mysql 服务 (TCP 三次握手)
- 执行 sql
- 断开 mysql 服务 (TCP 四次挥手)
- 长连接
- 连接 mysql 服务 (TCP 三次握手)
- 执行 sql
- 执行 sql
- ...
- 断开 mysql 服务 (TCP 四次挥手)
使用长连接的优缺点?
可以减少建立连接和断开连接的次数。 但使用长连接过多时,会导致 mysql 占用内存增多。 mysql 在执行查询过程中临时使用内存管理连接对象,这些连接对象资源只有在断开连接时才会释放。 如果长连接累计很多,将导致 mysql 服务占用内存很大,有可能被操作系统强制杀掉,这回导致 mysql 服务异常重启。
如何解决长连接的内存占用问题?
- 定期断开长连接。
- 客户端主动重置连接。 在代码里调用
mysql_reset_connection()。这个过程不需要重新建立连接,会恢复到刚创建连接时的状态。
在建立连接时,连接器干了哪些工作?
- 与客户通过 TCP 三次握手,建立起 TCP 连接
- 检查用户名和 密码
- 读取用户权限,后续在此连接的操作都基于此时读取到的权限。
查询缓存
MySQL 8.0 中以移除了缓存模块
客户端与 mysql 服务通过连接器建立连接后,客户端就可以向 mysql 服务发生 sql 语句了。mysql 服务在收到 sql 语句后,就会解析出 sql 语句的第一个字段, 看看是什么类型的语句。如果是查询语句,就会先去查询缓存里查找缓存数据,看看之前有没有执行过这条语句。
查询缓存是以 key-value 形式保存在内存的,key 为 sql 查询语句,value 为 sql 查询结果。
如果命中缓存,就直接将 value 返回给客户端。没有命中就继续往下执行,等执行完后,将查询结果存入查询缓存。
解析 SQL
正式执行 sql 查询语句之前,mysql 会先对 sql 进行解析。这个过程由解析器来完成。
解析器
- 词法分析
- 语法分析,构建语法树。不会去检查表或者字段存不存在。
执行 SQL
- prepare 阶段,预处理阶段
- optimize 阶段,优化阶段
- execute 阶段,执行阶段。