MySQL的基本架构
要深入了解MySQL,需要先窥其全貌,了解MySQL的架构是如何组成的,我们在执行一条SQL时都发生了什么。
上图是MySQL基本逻辑架构
下面分别看看架构中的各个组件分别起什么作用。
我们常说的安装MySQL是指安装MySQL服务端部分,也就是图中的Server和执行引擎部分,而我们常用的Navicat,命令行执行MySQL工具,各个语言的连接驱动等,都是客户端。
连接器
连接器负责跟客户端建立连接,获取权限,维持和管理连接。
- 在使用MySQL的时候,需要登录用户名和密码,连接器负责验证,如果用户名密码不正确就会报出
Access denied for user
的错误。 - 登录成功后连接器会查询登录用户的权限,之后,这个连接里的权限判断,都由此时查询到的连接决定。也就是说,这个连接建立之后,在这个连接断开之前,即使其他管理员用户修改了该用户的权限,对这个连接里的权限判断都没有影响。
- 关于连接状态,执行
show processlist
命令可以看到 此时可以看到有两行Command的值为Sleep,表示现在系统中有2个空闲连接。当空闲时间到达wait_timeout的时候后,连接器会控制这个连接自动断开。 - MySQL在执行过程中临时内存由连接对象管理,所以当长连接持续使用后可能会导致内存占用过大的问题。为了要解决这个问题,需要定期断开长连接,如果是5.7版本以上的MySQL用户通过执行mysql_reset_connection,这个操作能初始化连接资源,又不需要重新建立连接和登录校验。
查询缓存
在8.0以前的版本,MySQL是有查询缓存的。当MySQL执行完一个查询语句,会将执行结果以key-value的形式缓存到内存中,这里的key就是查询用的SQL语句,如果正在执行的SQL命中了查询缓存,就会将缓存的结果直接返回給客户端,不需要继续执行后续。如果没有命中缓存,MySQL就会继续执行后面的查询,然后将执行结果放入缓存。
那么,看起来能提高查询效率的查询缓存,为什么在8.0反而没有了呢?因为当查询的表数据被更新后,关于该表的缓存需要全部清空,对于更新频繁的表,查询缓存不光不会提高效率,还会降低效率,浪费资源。只有当业务使用的是纯静态表,查询缓存才会明显提高效率,现在对于这样的数据,往往在客户端就做了缓存,故而MySQL的查询缓存显得不必要。
在8.0以前的版本,可以按需设置是否使用查询缓存,可以将query_cache_type设置成DEMAND。这样对于默认呢的SQL语句,都不使用查询缓存,对于需要使用查询缓存的SQL语句,可以使用 SQL_CACHE
关键字显式指定。
比如:SELECT SQL_CACHE id FROM user
分析器
MySQL在这里对待执行的SQL进行分析
-
语法分析:用于判断该语句是否符合MySQL支持的SQL语法。如果不满足,会出现错误提示
-
还会在这里识别语句关键字,是查询还是更新,待执行的表名和列名等。
优化器
分析器分析出SQL需要做什么。优化器则决定了后续程序如何执行。
- 待查询的表中有多个索引时,应该使用哪个索引。
- 当SQL使用了联表查询时,优化器决定了按何种顺序连接各表。
执行器
完成了前面的准备工作,由执行器在这里执行SQL定义的操作。
- 先判断对于待执行的表有无权限,如果没有,就会报出无权限的错误,如果有,就会打开表继续执行。
- 根据表的存储引擎,执行该引擎提供的接口进行操作。执行的存储引擎提供的接口往往是“获取满足条件的下一行数据”,如果有索引,就获取满足索引条件的下一行数据,如果没有索引就直接获取表中的下一行数据。如此循环直到获取完毕。
在数据库的慢查询日志中,可以看到row_examined字段,就是执行器记录的调用存储引擎获取数据的累计的次数。