一条sql语句是如何执行的
sql语句的分析
MySQL介绍
MySQL 可以分为 Server 层和存储引擎层两部分。
Server层包括:连接器,查询缓存,分析器,优化器,执行器等,所有跨存储的功能都在这一层实现。比如:存储过程,触发器,试图
存储引擎:存储数据,提供读写接口。支持 InnoDB、MyISAM、Memory 等多个存储引擎
分析下面这条sql查询语句的执行逻辑
select * from T where ID=10;
第一步:连接器
连接器服合跟客户段建立连接,获取权限,维持和管理连接。
一般命令为:
mysql -h$ip -P$port -u$user -p
注:一个用户建立连接后,及时你用管理员账号修改了这个用户的权限,也不会影响以及存在的连接
客户端如果太长时间没动静,连接器就会自动将它断开。这个时间是由参数 wait_timeout 控制的,默认值是 8 小时。
第二步:查询缓存
建立完连接后你就,你就可以执行select语句了
MySQL拿到一个查询请求后,会先查询缓存,如果之前执行过这条语句,那么就会以key-value的形式缓存在内存中。
key :查询语句
value:查询结果
如果不存在查询缓存,那么会继续执行后续操作
注:大多数情况下不建议使用查询缓存,查询的弊大于利
MySQL 8.0 版本直接将查询缓存的整块功能删掉了
第三步:分析器
如果没有命中查询缓存,那么就开始执行真正的查询语句了。
首先MySQL会做词法分析:
你输入select 识别为一个查询语句
T 识别为表T
ID 识别为列ID
做完这些后就要开始语法分析
会根据你的SQL语句判断是否满足MySQL语法
第四步:优化器
经过分析器MySQL知道你要做什么,在执行前需要经过优化器处理
优化器是当你表里有多个索引的时候,决定使用哪个索引,在使用join的时候决定连接顺序
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。
优化器会决定使用哪个方案
第五步:执行器
分析器知道了要做什么,优化器知道了要怎么做,那么执行器就要开始执行了
首先会判断是否有权限,如果没有会返回错误提示
然后根据根据定义的引擎,去使用引擎接口
更新语句的执行
redo log日志
如果每次更新的时候都需要写进磁盘,然后磁盘找到对应的日志更新,那么整个IO成本太高了,为了解决这个问题,MySQL的使用者redo log
具体的实现流程
InnoDB引擎会先把记录写到redo log,并更新内存。InnoDB会在适当的时候将这个操作记录写道磁盘里面
注:redo log是由固定大小的
比如可以配置为一组 4 个文件,每个文件的大小是 1GB,那么这块rodo log总共就可以记录 4GB 的操作。
有了rodo log及时数据库异常重启,之前提交的数据也不会丢失
binlog 日志
上面说到的redo log是引擎层面的,binlog则是server层面的
binlog是早期没有InnoDB的产物,用来做归档
redo log和binlog不同
- redo log是InnoDB特有的,binlog是所有引擎都可以使用
- redo log是物理日志,binlog是逻辑日志
- redo log是循环写的,binlog是追加写入的
分析下面这条sql更新语句的执行逻辑
update T set c=c+1 where ID=2;
- 执行器先找到ID为2的记录
- 执行器拿到数据,并+1,并写入新的数据
- 引擎将更新操作记录的redo log,此时redo log处于prepare状态
- 执行器生成binlog,并把binlog写入磁盘
- 执行器调用引擎的事务提交接口,redo log提交,更新完成