当前位置: 首页 > 后端技术 > PHP

MySQL逻辑架构 - SQL语句的执行都经历了哪些步骤

时间:2023-03-30 00:15:10 PHP

MySQL逻辑架构——SQL语句的执行经过了哪些步骤?一般来说,MySQL可以分为两部分:服务器层和存储引擎层。Server层包括连接器、查询缓存、分析器、优化器和执行器,涵盖了MySQL的大部分核心服务功能,以及所有内置功能(如日期、时间、数学和加密功能等),所有跨存储引擎功能也在这一层实现,包括存储过程、触发器、视图等。存储引擎层负责数据的存储和检索。包括MySQL常见的存储引擎,包括MyISAM、InnoDB、Memory等,最常用的是InnoDB,这也是MySQL默认的存储引擎。也可以在创建表时手动指定存储引擎,使用以下语句:CREATETABLEt(iINT)ENGINE=;不同的存储引擎有不同的表数据访问方式,支持不同的功能。从图中可以看出,不同的存储引擎共享一个服务器层,也就是从连接器到执行器的部分。connector需要先登录MySQL客户端,所以需要一个connector来连接用户和MySQL数据库。我们一般使用mysql-h-P-u-p[]来登录MySQL并与服务器建立连接。虽然可以直接在-p后面的命令行写密码,但是这样可能会导致你的密码泄露。强烈建议不输入密码直接运行命令,然后在交互对话框中输入密码。完成TCP握手后,连接器会根据您输入的用户名和密码验证您的登录。如果用户名或密码错误,MySQL会提示Accessdeniedforuser,然后客户端程序结束执行。如果用户名和密码验证通过,连接器将检查您在权限表中拥有的权限。之后,这个连接中的权限判断逻辑就会依赖于此时读取的权限。这意味着用户成功建立连接后,即使你使用管理员账户修改用户的权限,也不会影响已有的连接权限。修改完成后,只有新连接才会使用新的权限设置。连接完成后,如果没有后续动作,则连接处于空闲状态,可以使用showprocesslist命令查看。mysql>showprocesslist;+--------+------------+--------------------+--------+---------+-----+---------+------------------+|编号|用户|主持人|分贝|命令|时间|------------------+--------+--------+------+----------+----------------+|214416|大师|124.126.130.4:29734|数据库名称|睡觉|13||空||214417||124.126.130.4:29754|数据库名称|查询|0|开始|显示进程列表|+--------+------------+------------------+--------+--------+------+----------+----------------+2rowsinset(0.07sec)Command栏显示Sleep这一行,表示系统中有空闲连接。如果客户端太长时间没有移动,连接器将自动断开连接。这个时间由参数wait_timeout控制,默认值为8小时。如果客户端断开连接后再次发送请求,会收到错误提示:LostconnectiontoMySQLserverduringquery。这时候如果想继续,就需要重新连接,然后执行请求。在数据库中,长连接是指连接成功后,如果客户端继续请求,将一直使用同一个连接。短连接是指每次执行几次查询后断开连接,重新建立一个新的连接用于下一次查询。建立连接的过程通常比较复杂,所以建议在使用过程中尽量减少建立连接的动作,即尽量使用长连接。但是全部使用长连接之后,你可能会发现有时候MySQL占用的内存增加的非常快。这是因为MySQL在执行过程中临时使用的内存是在connection对象中管理的。这些资源只有在连接断开时才会被释放。因此,如果长连接堆积起来,可能会导致内存占用过多而被系统强行杀掉(OOM)。从现象上看,MySQL重启异常。如何解决这个问题呢?您可以考虑以下两种选择。定期断开长连接。使用一段时间后,或者程序判断执行了占用内存大的查询,断开连接,需要重新连接查询。如果你使用的是MySQL5.7以上的版本,你可以在每次大操作后执行mysql_reset_connection重新初始化连接资源。这个过程不需要重新连接和重新认证,但是会将连接恢复到刚刚创建的状态。querycache连接完成后,就可以执行sql语句了,这行逻辑就会来到第二步:querycache。MySQL在得到一个执行请求后,首先会去查询缓存中查找这条SQL语句是否已经被执行过。之前执行的语句和结果会以键值对的形式直接存储在内存中。键是查询语句,值是查询的结果。如果通过key可以找到SQL语句,则直接返回SQL执行结果。如果该语句不在查询缓存中,则继续执行后续阶段。执行完成后,会将执行结果放入查询缓存中。可以看出,如果查询命中了缓存,MySQL可以直接返回结果,不需要进行后续的复杂操作,效率会很高。但在大多数情况下,不建议使用查询缓存,因为查询缓存失效非常频繁。只要对MySQL中的某张表进行了更新操作,那么这张表上的所有查询缓存都会失效。对于频繁更新的数据表,查询缓存的命中率会很低。除非你的业务是要静态表,否则会隔很长时间更新一次。比如一个系统配置表,那么对这个表的查询就适合做查询缓存。幸运的是,MySQL也提供了这种“按需使用”的方式。您可以将参数query_cache_type设置为DEMAND,这样查询缓存就不会被默认的SQL语句使用。对于确定使用查询缓存的语句,可以使用SQL_CACHE显式指定:selectSQL_CACHE*fromTwhereID=10;需要注意的是,MySQL8.0版本直接删除了querycache的全部功能。如果分析器没有命中查询缓存,它将开始实际执行SQL语句。首先,MySQL会分析你写的SQL语句。分析器会先做词法分析。你输入了一条由多个字符串和空格组成的SQL语句。MySQL需要识别其中的字符串是什么。什么。然后进行语法分析。语法分析器根据词法分析的结果,根据语法规则判断你输入的SQL语句是否符合MySQL语法。如果SQL语句不正确,会提示YouhaveanerrorinyourSQLsyntax。优化器经过分析器的词法分析和语法分析后,这条SQL是合法的,MySQL就知道你要干什么了。但是在执行之前,需要经过优化器的处理。当表中有多个索引时,优化器决定使用哪个索引;或者当一个语句有多个表关联(join)时,决定每个表的连接顺序。例如执行如下语句,该语句是执行两张表的连接:select*fromt1joint2using(ID)wheret1.c=10andt2.d=20;可以先从表t1中取c记录的ID值=10,然后根据ID值与表t2关联起来,然后判断t2中d的值是否等于20。也可以取先从表t2中取出d=20的记录的ID值,然后根据ID值关联到t1,再判断t1中c的值是否等于10。这两次执行的逻辑结果方法是一样的,但是执行效率会不一样,优化器的作用就是决定使用哪种scheme。优化器会决定你使用哪个索引和连接,并决定最高效的执行计划。执行者MySQL通过分析器知道你的SQL语句是否合法,你要做什么操作,通过优化器知道如何做效率最高,然后进入执行阶段,开始执行这条SQL语句。开始执行时,MySQL会先判断你是否有权限在要操作的表上执行这条语句。如果没有权限,会返回一个没有权限的错误(ERROR1142(42000):SELECTcommanddeniedtouser'foo'@'localhost'fortable'bar')。如果有权限,打开表继续执行。打开表时,执行器会根据表的引擎定义,使用引擎提供的接口查询数据并返回给客户端。至此,MySQL完成了一条语句的执行过程。参考《MySQL实战45讲》丁琪