有如下表格:
我们执行以下sql:
1 | select * from t_user where user_id=10000; |
接下来说这条SQL语句在MySQL中的完整执行流程。
1、MySQL客户端与服务器建立连接
如下图,建立过程:
- 客户端通过mysql命令发起连接请求;
- 经过三次握手后与服务端建立TCP连接;
- 连接器接收到请求之后使用用户密码进行身份验证;
- 验证通过之后,获取用户的权限信息缓存起来,该连接后面都是基于该缓存中的权限执行sql;
对于Java应用程序来说,一般会把建立好的连接放入数据库连接池中进行复用,只要这个连接不关闭,就会一直在MySQL服务端保持着,可以通过show processlist
命令查看,如下:
注意,这里有个Time,表示这个连接多久没有动静了,上面例子是656秒没有动静,默认地,如果超过8个小时还没有动静,连接器就会自动断开连接,可以通过wait_timeout
参数进行控制。
2、执行SQL
如下图,执行sql:
- 服务端接收到客户端的查询sql之后,先尝试从查询缓存中查询该sql是否已经有缓存的结果了,如果有则直接返回结果,如果没有则执行下一步;
- 分析器拿到sql之后会尝试对sql语句进行词法分析和语法分析,校验语法的正确性,通过之后继续往下执行;
- 优化器拿到分析器的sql之后,开始继续解析sql,判断到需要走什么索引,根据实际情况重写sql,最终生成执行计划;
- 执行器根据执行计划执行sql,执行之前会先进行操作权限校验;然后根据表存储引擎调用对应接口进行查询数据,这里的扫描行数就是指的接口返回的记录数,执行器拿到返回记录之后进一步加工,如本例子:
- 执行器拿到select * from t_user where user_id=10000的所有记录,在依次判断user_name是不是等于"arthinking",获取到匹配的记录。