【MySQL】基本架构
MySQL 基本架构
MySQL
主要由以下几个功能模块组成:
-
连接器。
-
查询缓存。
-
分析器。
-
优化器。
-
执行器。
-
存储引擎。
server
层:
连接器、查询缓存、分析器、优化器、执行器组成了server
层。
该层包含了所有的内置函数,所有的跨存储引擎功能也都在这一层,如存储过程、触发器、视图等。
存储引擎层:
存储引擎模块属于存储引擎层。
该层负责数据的存储和提取,其架构模式是插件式。
可以使用show engines
查看引擎信息。MySQL5.5.5
之后默认使用InnoDB
。
连接器
连接器,用于管理连接,权限验证。
创建连接
连接命令一般为:
|
|
完成TCP
握手后,连接器开始认证身份,此时会用到输入的用户名和密码。
如果用户名或者密码不对,返回"Access denied for user"
。
如果认证通过,连接器会到权限表获取用户拥有的权限,用于之后所有的权限判断逻辑。
如果该用户的权限被修改,对于已通过认证的连接,拥有的权限不会受影响。只有重新建立连接,才会使用新权限。
空闲连接
建立连接后,如果没有后续动作,该连接就处于空闲状态。可以使用show processlist
查看空闲中的连接。
如果一直保持空闲状态,到一定时间连接器会将这个连接断开,该时间受wait_timeout
控制,默认为8小时。
连接断开后,该连接再次发送请求的话,就会收到一个错误提醒。
长连接和短连接
长连接是指,连接成功后,后续的请求一直使用同一个连接。
短链接是指,连接成功后,只执行完成很少的几次查询,就断开连接,下次查询时再重新建立一个。
建立连接的过程比较复杂,所以应尽量使用长连接。但是在MySQL
中,使用长连接也会存在问题。
MySQL
执行过程中临时使用到的内存,是管理在连接对象里面的,在连接断开时,资源才会释放。如果长连接一直积累,就会导致内存占用太大,被系统强行杀掉,从而导致MySQL
异常重启。
要解决长连接问题,可以考虑两种方案:
-
定期断开长连接。
-
MySQL5.7
或之后版本,每次执行完一个较大操作,可以使用mysql_reset_connection
来初始化连接资源,包括事务回滚、锁释放等。初始化过程中,不会重连和重新验证权限,只会恢复到连接刚刚创建完的状态。
查询缓存
之前的查询语句和结果,会以key-value
对的形式,缓存在内存中。如果查询时能在缓存中找到这个key
,那么value
会被直接返回。如果找不到,才继续后面的阶段。
返回结果的时候,会做权限验证。
按需使用
查询缓存的失效非常频繁,一个表只要有更新,这个表上的所有查询缓存都会被清空。对于更新压力大的数据库来说,查询缓存的命中率非常低。
静态表可以使用查询缓存,如系统配置相关表。
MySQL8.0
已经删除了查询缓存。其它版本可以通过设置query_cache_type
进行控制。
query_cache_type
该参数有三个不同的值:
-
OFF
:关闭查询缓存。 -
ON
:缓存所有结果,除非在select
语句中使用SQL_NO_CACHE
禁止缓存。 -
DEMAND
:在select
语句中使用SQL_CACHE
时进行缓存。
分析器
分析器会进行词法分析、语法分析。
除了检查语法对不对之外,还会检查库名、表名和字段名是否正确。
优化器
优化器会根据SQL
语句,生成多个查询路径树,然后从中选择一个最优解。如有多个索引时,决定使用哪个索引;使用join
时,决定各个表的连接顺序等。
使用优化器之前,会调用precheck
验证权限。
执行器
根据表的引擎定义,调用对应的引擎接口,从而完成SQL
语句的执行。
执行前,需要判断一下是否有表的执行权限。
查询的执行流程
现在以查询语句为例,说明执行器的执行流程。
对于无索引数据:
- 调用接口取这个表的第一行。
- 如果满足要求就加入结果集,如果不满足就跳过。
- 直到这个表的最后一行,然后将结果集返回客户端。
对于有索引数据:
- 取满足条件的第一行,加入结果集。
- 循环取满足条件的下一行。
rows_examined
慢查询日志中有一个rows_examined
参数,表示语句执行过程中扫描了多少行。
执行器每次调用引擎获取数据时,会对rows_examined
进行累加,即该值等于执行器通过引擎接口获取的数据行数。
但是执行器每调用一次接口,引擎内部可能扫描多行。