最近开始在学习mysql相关知识,自己根据学到的知识点,根据自己的理解整理分享出来,本篇文章会分析下一个sql语句在mysql中的执行流程,包括sql的查询在mysql内部会怎么流转,sql语句的更新是怎么完成的。
一、mysql架构分析
下面是mysql的一个简要架构图:
mysql主要分为Server层和存储引擎层
Server层:主要包括连接器、查询缓存、分析器、优化器、执行器等,所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图,函数等,还有一个通用的日志模块 binglog日志模块。
存储引擎: 主要负责数据的存储和读取,采用可以替换的插件式架构,支持InnoDB、MyISAM、Memory等多个存储引擎,其中InnoDB引擎有自有的日志模块redolog 模块。
InnoDB 5.5.5版本作为默认引擎。
连接器
主要负责用户登录数据库,进行用户的身份认证,包括校验账户密码,权限等操作,如果用户账户密码已通过,连接器会到权限表中查询该用户的所有权限,之后在这个连接里的权限逻辑判断都是会依赖此时读取到的权限数据,也就是说,后续只要这个连接不断开,即时管理员修改了该用户的权限,该用户也是不受影响的。
查询缓存
连接建立后,执行查询语句的时候,会先查询缓存,Mysql会先校验这个sql是否执行过,以Key-Value的形式缓存在内存中,Key是查询预计,Value是结果集。如果缓存key被命中,就会直接返回给客户端,如果没有命中,就会执行后续的操作,完成后也会把结果缓存起来,方便下一次调用。当然在真正执行缓存查询的时候还是会校验用户的权限,是否有该表的查询条件。
Mysql 查询不建议使用缓存,因为对于经常更新的数据来说,缓存的有效时间太短了,往往带来的效果并不好,对于不经常更新的数据来说,使用缓存还是可以的,Mysql 8.0 版本后删除了缓存的功能,官方也是认为该功能在实际的应用场景比较少,所以干脆直接删掉了。
分析器
mysql 没有命中缓存,那么就会进入分析器,分析器主要是用来分析SQL语句是来干嘛的,分析器也会分为几步:
第一步,词法分析,一条SQL语句有多个字符串组成,首先要提取关键字,比如select,提出查询的表,提出字段名,提出查询条件等等。做完这些操作后,就会进入第二步。
第二步,语法分析,主要就是判断你输入的sql是否正确,是否符合mysql的语法。
完成这2步之后,mysql就准备开始执行了,但是如何执行,怎么执行是最好的结果呢?这个时候就需要优化器上场了。
优化器
优化器的作用就是它认为的最优的执行方案去执行(虽然有时候也不是最优),比如多个索引的时候该如何选择索引,多表查询的时候如何选择关联顺序等。
执行器
当选择了执行方案后,mysql就准备开始执行了,首先执行前会校验该用户有没有权限,如果没有权限,就会返回错误信息,如果有权限,就会去调用引擎的接口,返回接口执行的结果。
二、语句分析
2.1 查询语句
说了以上这么多,那么究竟一条sql语句是如何执行的呢?其实我们的sql可以分为2中,一种是查询,一种是更新(增加,更新,删除)。我们先分析下查询语句,语句如下:
select * from tb_student A where A.age='18' and A.name='张三';
结合上面的说明,我们分析下这个语句的执行流程:
先检查该语句是否有权限,如果没有权限,直接返回错误信息,如果有权限,在mysql8.0版本以前,会先查询缓存,以这条sql语句为key在内存中查询是否有结果,如果有直接缓存,如果没有,执行下一步。
通过分析器进行词法分析,提取sql语句的关键元素,比如提取上面这个语句是查询select,提取需要查询的表名为tb_student,需要查询所有的列,查询条件是这个表的id='1'。然后判断这个sql语句是否有语法错误,比如关键词是否正确等等,如果检查没问题就执行下一步。
接下来就是优化器进行确定执行方案,上面的sql语句,可以有两种执行方案:
a.先查询学生表中姓名为“张三”的学生,然后判断是否年龄是18。
b.先找出学生中年龄18岁的学生,然后再查询姓名为“张三”的学生。
那么优化器根据自己的优化算法进行选择执行效率最好的一个方案(优化器认为,有时候不一定最好)。那么确认了执行计划后就准备开始执行了。
进行权限校验,如果没有权限就会返回错误信息,如果有权限就会调用数据库引擎接口,返回引擎的执行结果。
2.2 更新语句
以上就是一条查询sql的执行流程,那么接下来我们看看一条更新语句如何执行的呢?sql语句如下:
update tb_student A set A.age='19' where A.name='张三';
我们来给张三修改下年龄,在实际数据库肯定不会设置年龄这个字段的,不然要被技术负责人打的。其实条语句也基本上会沿着上一个查询的流程走,只不过执行更新的时候肯定要记录日志啦,这就会引入日志模块了,mysql 自带的日志模块式binlog(归档日志),所有的存储引擎都可以使用,我们常用的InnoDB引擎还自带了一个日志模块redo log,我们就以InnoDB模式下来探讨这个语句的执行流程。流程如下:
先查询到张三这一条数据,如果有缓存,也是会用到缓存。
然后拿到查询的语句,把 age 改为19,然后调用引擎API接口,写入这一行数据,InnoDB引擎把数据保存在内存中,同时记录redo log,此时redo log进入prepare状态,然后告诉执行器,执行完成了,随时可以提交。
执行器收到通知后记录binlog,然后调用引擎接口,提交redo log 为提交状态。
更新完成。
这里肯定有同学会问,为什么要用两个日志模块,用一个日志模块不行吗?这就是之前mysql的模式了,MyISAM引擎是没有redo log的,那么我们知道它是不支持事务的,所以并不是说只用一个日志模块不可以,只是InnoDB引擎就是通过redo log来支持事务的。那么,又会有同学问,我用两个日志模块,但是不要这么复杂行不行,为什么redo log 要引入prepare预提交状态?这里我们用反证法来说明下为什么要这么做?
先写redo log 直接提交,然后写 binlog,假设写完redo log 后,机器挂了,binlog日志没有被写入,那么机器重启后,这台机器会通过redo log恢复数据,但是这个时候bingog并没有记录该数据,后续进行机器备份的时候,就会丢失这一条数据,同时主从同步也会丢失这一条数据。
先写binlog,然后写redo log,假设写完了binlog,机器异常重启了,由于没有redo log,本机是无法恢复这一条记录的,但是binlog又有记录,那么和上面同样的道理,就会产生数据不一致的情况。
如果采用redo log 两阶段提交的方式就不一样了,写完binglog后,然后再提交redo log就会防止出现上述的问题,从而保证了数据的一致性。那么问题来了,有没有一个极端的情况呢?假设redo log 处于预提交状态,binglog也已经写完了,这个时候发生了异常重启会怎么样呢? 这个就要依赖于mysql的处理机制了,mysql的处理过程如下:
判断redo log 是否完整,如果判断是完整的,就立即提交。
如果redo log 只是预提交但不是commit状态,这个时候就会去判断binlog是否完整,如果完整就提交 redo log, 不完整就回滚事务。
最近,我开始学习与MySQL有关的知识,根据学到的知识点,根据自己的理解和汇编,本文将分析下面的SQL语句的执行流程在MySQL,包括如何在SQL查询它会在mysql中流动。如何更新sql语句。
一,mysql架构分析。
以下是mysql的简要架构图:
Mysql主要分为服务器层和存储引擎层
服务器层:主要包括连接器,查询缓存,分析器,优化器,执行器等。交叉存储引擎的所有功能都在该级别实现,例如存储过程,触发器,视图,功能等,以及通用binglog注册模块注册模块。
存储引擎:主要负责存储和读取数据。它采用可更换的插件架构,兼容多种存储引擎,如InnoDB,MyISAM和Memory。 InnoDB引擎有自己的模块模块redolog注册。
InnoDB版本5.5.5是默认引擎。
连接器
主要负责用户的登录数据库,用户身份验证,包括验证帐户密码,权限等。如果已传递用户帐户的密码,则连接器将在权限表中查询用户的所有权限,然后查询此连接中的权限。逻辑判断将依赖于允许数据在这段时间被读取,也就是说,如果连接不被中断,即时管理员修改用户的许可,并且用户也不会受到影响。
缓存查询
建立连接后,执行查询时,将首先查询缓存。 Mysql将首先验证sql是否已被执行。它以Key-Value的形式存储在缓存中。 Key是查询期望,Value是结果集。如果按下缓存键,它将直接返回给客户端。如果没有命中,将执行以下操作。完成后,结果将存储在缓存中以进行下一次调用。当然,当实际执行缓存查询时,将验证用户的权限以及表的查询条件是否可用。
不建议咨询MySQL使用缓存,因为对于频繁更新的数据,缓存的有效时间太短,往往效果不好。对于未经常更新的数据,仍然可以使用缓存,Mysql 8.0删除版本后,将删除缓存的功能。该官员还认为,在实际应用的情况下,该功能较少,因此它被简单删除。
分析仪
Mysql没有到达缓存内存,那么它将进入分析器,分析器主要用于分析SQL语句,分析器也将分为几个步骤:
第一步,词法分析,一个SQL语句由几个字符串组成,首先提取关键字,如何选择,查询表,字段名称,查询条件等。完成此操作后,您将进入第二步。第二步,分析,主要包括确定您输入的sql是否正确以及它是否符合mysql的语法。
完成这两个步骤后,mysql已准备好开始执行,但如何执行,如何执行是最好的结果?这次你需要优化器来玩。
优化
优化器的作用是,它认为对运行性能的最佳方案(尽管有时不是最优的),如当查询在多个表中作出选择时,多个索引,如何选择关联的顺序的索引。
执行器
选择执行计划后,mysql就可以开始执行了。在执行之前,它将验证用户是否具有权限。如果没有权限,则会返回错误消息。如果有权限,它将调用引擎接口并返回接口。执行的结果。
二,陈述分析
2.1咨询声明
他说了这么多,那么SQL语句到底是怎么执行的?实际上,我们的sql可以分为2个,一个是查询,一个是更新(添加,更新,删除)。首先我们分析查询,语句如下:
从tb_student A中选择*,其中A.age='18'和A.name='Zhang San';
结合前面的说明,我们分析了这个声明的执行流程:
如果首先检查该语句是允许的,如果没有权限,直接返回错误信息,如果有许可版本mysql8.0之前,先查询缓存,使用此SQL语句在内存中的关键看有结果,如果有直接缓存,如果没有,请转到下一步。
通过词法分析仪,提取SQL语句的关键要素,如提取的上述声明是选择查询,提取要征询表的名称是tb_student,你应该可以看到所有列,查询条件为id='1'此表。然后,确定sql语句是否有语法错误,例如,如果关键字是正确的等等,如果检查不是问题,请执行下一步。
以下是确定执行计划的优化器,以前的SQL语句有两种实现方案:
首先,在学生表格上核实名字为“张三”的学生,然后判断年龄是否为18岁。
湾首先,找出这位18岁学生是谁,然后询问名为“张三”的学生。
然后,优化器根据自己的优化算法选择最佳执行效率(优化器认为有时它不一定是最好的)。然后,在确认执行计划后,您就可以开始执行了。
执行许可证验证。如果没有权限,则会返回错误消息。如果有权限,将调用数据库引擎接口以返回引擎执行结果。
2.2更新状态以上是查询SQL执行过程,然后我们观察如何执行更新指令。 SQL语句如下:
更新tb_student A set A.age='19',其中A.name='张三';
改变张三的年龄。在真实数据库中,年龄字段肯定不会建立,否则它将由技术领导者播放。事实上,语句基本按照前面查询的流量,但注册必须在录制时更新完成,这将引进注册模块,MySQL使用模块二进制日志日志(日志文件),都可以使用存储引擎。我们常用的InnoDB引擎还附带一个注册表模块来重做注册表。我们将在InnoDB模式中讨论该语句的执行流程。过程如下:
首先查询张三的数据,如果有缓存,它也会使用缓存。
然后得到的查询语句,年龄改为19,然后调用API发动机,在存储器中输入数据,InnoDB引擎存储数据和记录重做日志,重做日志进入状态准备然后告诉执行实现已完成并准备发送。
一旦执行程序收到通知,它就会注册binlog,然后调用引擎接口并将重做记录作为确认状态发送。
更新完成。
这里肯定会有一些学生会问,为什么要使用两个注册模块,不能使用注册模块?这是这样一个MySQL的,MyISAM引擎不是重做日志,那么我们就知道不支持事务,所以这并不意味着你不能用一个单一的登记模块,但是InnoDB引擎支持事务通过重做记录。然后,有些学生会问,我使用了两个注册模块,但是没有那么复杂,我为什么要重做注册进入预先确认准备状态?在这里,我们使用反证据方法来解释为什么我们应该这样做?
一是直接写重做日志,然后键入二进制日志,假设重做日志写入后,机器锁,记录二进制日志不写,然后在计算机重新启动,这台机器将检索数据通过重做记录,但这次bingog没有。通过注册此数据,当备份机器时,数据将丢失,主从同步也将丢失此数据。
首先写入binlog,然后输入redo,假设写入了binlog,机器会异常重启。由于没有重做记录,机器无法检索此记录,但是binlog有记录,因此出现与前一个记录相同的原因。数据不一致当使用两阶段的方法中的重做日志它是不同的,在写入后binglog,然后发送重做日志将避免上述问题,从而保证数据的一致性。然后是问题:是否存在极端情况?假设重做记录处于事先确认状态,则binglog已经被写入。发生异常重启时会发生什么?这取决于mysql的处理机制。 mysql的处理如下:
确定重做记录是否完整。如果故障已完成,请立即发送。
如果重做记录先前已确认但尚未确认,则此时将确定binlog是否完整。如果重做记录未完整发送,则事务将回滚不完整。
上海IT外包服务网 链接:http://www.linemore.com