文章目录
- sql语句的执行过程
- 查询语句select的执行过程
- 准备工作
- 过程解析
- 客户端
- 连接器
- 查缓存
- 分析器
- 优化器
- 执行器
- 更新语句update的执行过程
- redo log
- binlog
- redo log 与binlog不同点
sql语句的执行过程
查询语句select的执行过程
准备工作
如我们通过执行界面创建一个表user
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(20) NOT NULL COMMENT '主键id',
`name` varchar(50) NOT NULL COMMENT '用户名称',
`phone` varchar(50) NOT NULL COMMENT '用户手机号',
PRIMARY KEY (`id`),
UNIQUE INDEX `idx_id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
插入1条记录,
insert into user values(1,'张三','18790098898');
执行
select * from user;
结果
mysql> select * from user;
+----+--------+-------------+
| id | name | phone |
+----+--------+-------------+
| 1 | 张三 | 18790098898 |
+----+--------+-------------+
1 row in set (0.00 sec)
过程解析
一条简单的select语句大致有以下阶段:
- 客户端
- 连接器
- 查询缓存
- 分析器
- 优化器
- 执行器
- 存储引擎
客户端
执行mysql,在navicat,cmd,terminal等应用端执行sql
连接器
负责与客户端连接,建立,获取,维持连接等。
建立连接之后,默认维持时间为8小时,超时则会断开,由wait_timeout 控制
查缓存
如果查到结果则直接返回,否则执行第4-7步
MySQL 执行过的语句与结果会以 key-value 的结构缓存在内存中。key 是查询的语句,value 是查询的结果。
因此查询请求进入,会先到查询缓存,如果在缓存中有 key,则将value 就会被直接返回给客户端,否则执行后面的操作
注:
查询缓存只要有对一个表的更新,这个表上所有的查询语句对应的缓存都将清空。MySQL 8.0 版本不再支持查询缓存
分析器
主要有:语法分析,词法分析。
词法分析主要分析关键词有没有,是否存在,如select, where
语法分析主要分析sql语句是否满足sql的语法, 如关键词输错,join没有条件 on等
优化器
经过分析器后,mysql得知语句的执行内容,优化器的工作就是对执行内容进行一个优化,如多个索引决定使用哪个索引;有多表关联(join)的时候,决定哪个表是主表,哪个表是关联表。
执行器
执行器的工作为执行语句,使用存储引擎提供的接口。如调用存储引擎接口,取得第一行,判断是否满足条件的数据,是则存到结果集,不是则取下一行。
数据库的慢查询日志中看到一个 rows_examined 的字段,这个是调用存储引擎扫描的次数,实际上调用一次存储引擎,存储引擎内部可能扫描多次,因此 引擎扫描行数跟 rows_examined 不完全相同
整体执行流程图:
引用自极客时间mysql实战45讲:学习连接
从整体流程图可看出,整体sql分2大块:server层和引擎层
更新语句update的执行过程
如我们要更改张三的手机号,执行语句为:
update user set phone =13790098898 where id =1;
执行成功
mysql> update user set phone =13790098898 where id =1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
查询结果
mysql> select * from user;
+----+--------+-------------+
| id | name | phone |
+----+--------+-------------+
| 1 | 张三 | 13790098898 |
+----+--------+-------------+
1 row in set (0.00 sec)
首先,查询语句的流程更新语句也同样会执行。在查询缓存的流程,更新的时候会将所有缓存结果清除,注:mysql 8.0不再支持缓存查询
除此之外,更新语句有两个重要的日志模块:redo log和binlog
redo log
- redo log 为重做日志,或成为回滚日志,在InnoDB存储引擎层 才会有。其作用是提高sql更新效率。
- 若每次执行更新语句,都要从磁盘查找到对应的记录,更新,并保存到磁盘中,若更新操作频繁,磁盘IO,查找的成本是很高的。
- InnoDB引擎每次执行更新语句时,将记录写进redo log并且更新内存,当系统空闲的时候,会统一将redo log的记录更新到磁盘
- InnoDB 的 redo log 是固定大小的,可以设置,redo log 通常有两个标志:write pos(当前写位置),checkpoint(要擦出的位置)。当更新一条记录,write pos会想checkpoint方向移动,当write pos要到达checkpoint位置时,标示redo log 内存已满,不能继续记录,要将redo log的记录更新到磁盘,并且清空redo log才能继续记录。
binlog
binlog 为server层的归档日志,由于mysql自带的存储引擎为MyISAM,MyISAM没有没有 crash-safe 的能力,binlog 日志只能用于归档。
而 InnoDB 以插件形式引入 MySQL 的,使用 redo log 来实现 crash-safe 。
redo log 与binlog不同点
待更新…