MySQL基本架构
下图是来自MySQL官方的架构图
从上图可以看出,整个mysql整体大致分为几个部分:
- connectors
- mysql组件:连接池,优化器,解析器,缓存等
- 插件式存储引擎,如InnoDB,MyISAM等
- 文件系统
其中connectors属于客户端与mysql server对接的接口,如JDBC, ODBC等,而文件系统属于硬件基础设施。
MySQL Server主要包含MySQL各个组件以及存储引擎。上图中虽然把文件系统也算在MySQL Server内,但我认为MySQL Server主要是使用了文件系统而已,是否把文件系统给包含进来其实都可以,无关紧要。
SQL执行过程
当我们连接mysql并执行一条语句时,整个过程是怎么样的呢?请看下图:
上图中,绿色部分属于MySQL Server。
当执行一条SQL语句时:
- 客户端必须先与MySQL Server建立连接,获得授权
- 查询缓存,如果缓存中有之前执行过一样的SQL的结果,那么直接返回该结果
- 如果没有缓存,则将SQL语句交给分析器进行分析,如果SQL语句不合法,返回错误
- 优化器对要执行的SQL进行优化,如选择合适的索引
- 将分析并优化过的SQL任务交给执行器进行执行
- 存储引擎真正执行数据的存储
以上就是一条SQL语句的整个执行过程
组件
连接池
当我们在客户端执行mysql -u username -p password
时,客户端将会和mysql建立起一个tcp长连接,mysql会对你输入的用户名密码进行校验,并从权限表中查询你的权限。
有时我们启动了一个mysql服务,却发现没法在别的机器远程连接,很有可能因为mysql权限表限制了只能localhost本地连接。
可以查看mysql.user表:
上图中Host为%
表示可允许远程连接,如果你的环境只有一条localhost,那么可以使用以下命令将localhost修改为%:
update user set host=’%’ where user=’root’;
或者新建一条记录:
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'your password' WITH GRANT OPTION;
FLUSH RIVILEGES;
建立连接之后,如果客户端没有发出任何sql给mysql server,那么该连接就会被认为是空闲连接,空闲时间超过8小时,连接将被自动释放。
可以使用以下命令查看空闲释放时间的配置(单位是秒):
mysql> show variables like 'wait_timeout';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout | 28800 |
+---------------+-------+
1 row in set (0.00 sec)
查询缓存
MySQL每次查询后,都会将查询结果缓存下来,如果下次查询一样的语句,则会直接使用缓存。但有个严重的问题,一旦数据有更新,缓存将会失效,所以有时候缓存往往会拖累mysql。
因此在mysql8.0,已经将缓存模块直接删除了,所以我们一般不推荐使用查询缓存。可以使用以下配置禁用缓存:
# vi my.cnf
query_cache_type=0
query_cache_size=0
分析器
分析器将会对sql语句做语法分析,词法分析,简单来说就是检查你的语句是否有误,该语句是select还是update,操作的表是哪张表。一旦有误,则直接返回错误
优化器
优化器将对执行方案进行优化,它会决定该语句是否使用索引,使用哪个索引等。我们常用explain
命令查看sql语句优化后的执行方案,如:
mysql> explain select * from user;
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
| 1 | SIMPLE | user | ALL | NULL | NULL | NULL | NULL | 2 | NULL |
+----+-------------+-------+------+---------------+------+---------+------+------+-------+
1 row in set (0.00 sec)
执行器
执行器是SQL语句的执行者,不过它本身其实也是调用存储引擎提供的接口进行执行。
存储引擎所提供的接口是比较基础的接口,例如查询一张表的全部数据时,执行器会不断调用储存引擎的接口遍历表数据,直到没有数据为止。而不是直接把整个执行计划丢给存储引擎然后就得到一个结果。
总的来说,存储引擎会提供一些基础的接口,然后执行器根据优化后的执行计划一步步执行整个计划