mysql执行流程
mysql架构:server层和存储引擎层
- Server 层:负责建立连接、分析和执行 SQL
- 存储引擎层:负责数据的存储和提取
第一步:连接器
# -h 指定 MySQL 服务得 IP 地址,如果是连接本地的 MySQL服务,可以不用这个参数;
# -u 指定用户名,管理员角色名为 root;
# -p 指定密码,如果命令行中不填写密码(为了密码安全,建议不要在命令行写密码),就需要在交互对话里面输入密码
mysql -h$ip -u$user -p
mysql基于TCP协议进行传输,所以会进行三次握手
如何查看 MySQL 服务被多少个客户端连接了?
空闲连接会一直占用着吗?
mysql> show variables like 'wait_timeout';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| wait_timeout | 28800 |
+---------------+-------+
1 row in set (0.00 sec)
wait_timeout默认是8小时(28800s),超过时间会自动断开
手动断开连接:kill connection + id
mysql> kill connection +6;
Query OK, 0 rows affected (0.00 sec)
MySQL 的连接数有限制吗?
mysql> show variables like 'max_connections';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 151 |
+-----------------+-------+
1 row in set (0.00 sec)
怎么解决长连接占用内存的问题?
1. 定期断开长连接
2. mysql5.7版本实现了mysql_reset_connection():客户端主动重置连接
总结一下:
- 与客户端进行 TCP 三次握手建立连接;
- 校验客户端的用户名和密码,如果用户名或密码不对,则会报错;
- 如果用户名和密码都对了,会读取该用户的权限,然后后面的权限逻辑判断都基于此时读取到的权限
第二步:查询缓存
Query Cache:查询语句的缓存
以key-value的形式存储
key:SQL查询语句
value:SQL语句查询的结果
其实查询缓存挺鸡肋的
机制:如果一个表进行了更新操作,那么该表缓存的数据会被全部清空,所以频繁更新的表,缓存的命中率很低
mysql8.0直接将查询缓存删除了
之前的版本可以通过将query_cache_type 设置成 DEMAND,使其不是用查询缓存
第三步:解析sql
词法分析
例如:SQL语句 select username from userinfo
关键字 | 非关键字 | 关键字 | 非关键字 |
---|---|---|---|
select | username | from | userinfo |
语法分析
判断语法是否有误,如果正确就会构建SQL语法树
第四步:执行sql
SELECT 查询语句有三个阶段:
- prepare 阶段,也就是预处理阶段;
- optimize 阶段,也就是优化阶段;
- execute 阶段,也就是执行阶段;
预处理器:
- 检查 SQL 查询语句中的表或者字段是否存在;
- 将
select *
中的*
符号,扩展为表上的所有列;
MySQL 5.7 判断表或字段是否存在的工作,是在词法分析&语法分析之后,prepare 阶段之前做的,所以不纠结是在解析器里做的还是执行器里做的
优化器:
考虑查询成本
是否使用索引
- key=PRIMARY:主键索引
- key=null, type=ALL:全表扫描
- key=idx_name, type=range, possible_keys=PRIMARY, idx_name:覆盖索引
TIP:
查询语句最前面加个
explain
命令,这样就会输出这条 SQL 语句的执行计划,然后执行计划中的 key 就表示执行过程中使用了哪个索引,比如下图的 key 为PRIMARY
就是使用了主键索引。
执行器
- 主键索引查询
- 全表扫描
- 索引下推