欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MySQL中的sql语句执行过程

程序员文章站 2024-03-25 17:16:16
...

MySQL的基本结构

MySQL中的sql语句执行过程

Server层

有以下组件

连接器

在客户端登录Mysql时进行身份认证和权限确认

缓存

在进行select语句时,会优先查询的区域,同时在发现查询不到时会从表中查询并缓存到这个组件。顾名思义。

分析器

准确的说是语义分析器,即分析sql语句是否正确

优化器

优化sql语句到底层最优的方式从而执行sql语句,比如如何选择索引,如何联表,但只是理论最优,不一定是实际最优。

执行器

执行语句并从存储引擎层获取数据返回,与引擎交互的层。

binlog

熟悉的都知道,日志模块,记录日志

Server层主要实现了存储过程、触发器、视图、函数等功能。

存储引擎层

简单说就是负责数据的读和写,可以替换,有很多类型的存储引擎,默认情况下为InnoDB,比较常用的还有MyISAM、Memory等多个存储引擎。

MyISAM

不支持事务和行级锁,因此不支持并发事务,而且无法保证可用性,容错性很差。但是也有可取之处,比如全文索引、压缩、空间函数等,性能很好。

InnoDB

支持行级锁,支持事务,外键等功能,具有安全回滚的能力。
同时也支持MVCC:可以使用乐观锁和悲观锁来实现。只在读取已提交和可重复读两个隔离级别下工作。(数据库事务四个隔离级别,读取未提交,读取已提交,可重复读,可串行化)
效率上则未必比MyISAM弱,要看具体的实际场景。

两者在索引方面的区别

两者都使用的B+树(可自行查询),MyISAM引擎的叶节点data域存放数据的地址。被称为非聚簇索引。InnoDB数据文件本身是索引文件,索引文件和数据文件分离,树的叶节点data域保存了完整的数据记录,数据文件本身是主索引,而数据表主键则是索引的键值,被称为聚簇索引。

实例分析

大的来分,sql语句不外乎两种,查询与修改,因为增删改都可以算是修改。

查询语句

举个简单例子如下

select * from student Tate where Tate.sex='M' and Tate.num=1;

执行流程如下:

  1. 检查权限。若无则报错,若正确则下一步
  2. 查询缓存(8.0及更高不再查询)。如果有则直接返回,若无,继续下一步。
  3. 进入分析器分析词法,提取出语句中的操作,先找到select确认为查询操作,后找到from后的表名student进行查询,然后判断是否存在语法问题,若有则报错,无则继续下一步。
  4. 这就到了优化器的层面,确认理论最优的查询方案,比如这条语句,我们有两种做法,把性别=M的全部找出来再找num=1的或是把num=1的先找出来再找性别M的(再者也有联表顺序之类的语句也会有不同的执行过程)通过内部的相关算法选择理论上认为最优的过程进行执行操作,然后进入下一步
  5. 接下去再次进行权限检查去调用底层的存储引擎提供的相关接口,然后返回结果。

修改语句

同样举个例子

update student Tate set Tate.money=10000 where Tate.num=1;

和查询不一样,这里面主要涉及数据的修改,为了数据库的安全回复,这里就要用到上面提到的binlog组件,也就是日志组件,当然引擎也存在相应的日志组件。
具体过程如下:

  1. 查询num=1的所有数据(与查询语句类似)
  2. 根据查询语句修改money字段,调用引擎接口保存数据,在引擎的日志模块中记录,并返回执行器信号,记录此时处于“准备”阶段(还未commit)
  3. 执行器收到信号后将操作记录到binlog日志组件中,然后再次调用引擎接口,设置引擎的日志模块中这条日志为commit状态。

异常处理

因为两个日志的存在会引发很多问题。

为什么存在两个日志

首先先弄清楚这个问题,其实是可以不存在两个日志的,这应该算是个版本更新的问题,5.5之前版本Mysql采用的是MyISAM引擎,而上面提到了,这个是不存在日志模块的,而InnoDB是存在的,名字叫redo log。

极端情况

redo log正在准备阶段,但是binlog写完还未调用引擎接口的时候宕机了,造成数据的不一致。

解决方法

重启之后Mysql会对redolog进行检查,如果发现是commit状态,就提交事务。
如果发现是准备阶段,那就再去判断binlog是否已经存在完整的记录,如果是则修改redolog为commit,如果不是则进行回滚,重新执行事务。

相关标签: MYSQL mysql sql