一条SQL查询语句的执行流程

image-20220927150319024

1
select * from T where ID=10;

连接器

连接器负责跟客户端建立连接、获取权限、维持和管理连接

1
mysql -h$ip -P$port -u$user -p
  • 如果用户名或密码不对,你就会收到一个”Access denied for user”的错误,然后客户端程序结束执行。
  • 如果用户名密码认证通过,连接器会到权限表里面查出你拥有的权限。

长连接 & 短连接

长连接是指连接成功后,如果客户端持续有请求,则一直使用同一个连接。

短连接则是指每次执行完很少的几次查询就断开连接,下次查询再重新建立一个。

查询缓存

之前执行过的语句及其结果可能会以key-value对的形式,被直接缓存在内存中。key是查询的语句,value是查询的结果。但查询缓存的失效非常频繁,只要有对一个表的更新,这个表上所有的查询缓存都会被清空。MySQL 8.0版本无查询缓存功能。

分析器

分析器先会做“词法分析”。MySQL需要识别出SQL语句的字符串分别是什么,代表什么。

MySQL从你输入的”select”这个关键字识别出来,这是一个查询语句。它也要把字符串“T”识别成“表名T”,把字符串“ID”识别成“列ID”。

做完了这些识别以后,就要做“语法分析”。根据词法分析的结果,语法分析器会根据语法规则,判断你输入的这个SQL语句是否满足MySQL语法。

优化器

优化器是在表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联(join)的时候,决定各个表的连接顺序。

如下面这条语句

1
select * from t1 join t2 using(ID)  where t1.c=10 and t2.d=20;
  • 既可以先从表t1里面取出c=10的记录的ID值,再根据ID值关联到表t2,再判断t2里面d的值是否等于20。
  • 也可以先从表t2里面取出d=20的记录的ID值,再根据ID值关联到t1,再判断t1里面c的值是否等于10。

两种执行方法的逻辑结果是一样的,但是执行的效率会有不同,而优化器的作用就是决定选择使用哪一个方案。

执行器

开始执行的时候,要先判断一下你对这个表T有没有执行查询的权限,如果没有,就会返回没有权限的错误。

一条SQL更新语句的执行流程

1
update T set c=c+1 where ID=2;

更新流程涉及两个重要的日志模块。redo log(重做日志)和 binlog(归档日志)

redo log

WAL(Write_Ahead Logging)技术: 先写日志,再写磁盘。

当有一条记录需要更新的时候,InnoDB引擎就会先把记录写到redo log里面,并更新内存,这个时候更新就算完成了。同时,InnoDB引擎会在适当的时候,将这个操作记录更新到磁盘里面。

InnoDB的redo log是固定大小的

image-20220927154602131

write pos是当前记录的位置,一边写一边后移,写到第3号文件末尾后就回到0号文件开头。checkpoint是当前要擦除的位置,也是往后推移并且循环的,擦除记录前要把记录更新到数据文件。

有了redo log,InnoDB就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为crash-safe

binlog

两种日志的不同

  • redo log是InnoDB引擎特有的;binlog是MySQL的Server层实现的,所有引擎都可以使用。
  • redo log是物理日志,记录的是“在某个数据页上做了什么修改”;binlog是逻辑日志,记录的是这个语句的原始逻辑,比如“给ID=2这一行的c字段加1”。
  • redo log是循环写的,空间固定会用完;binlog是可以追加写入的。

image-20220927155212268

redo log的写入拆成了两个步骤:prepare和commit,这就是”两阶段提交”。