MySQL笔记(5)-- SQL执行流程,MySQL体系结构
MySQL笔记
- MySQL的体系结构,可以清楚地看到 SQL 语句在 MySQL 的各个功能模块中的执行过程:Server层包括连接层、查询缓存、分析器、优化器、执行器等,涵盖MySQL的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),实现所有跨存储引擎的功能比如存储过程、触发器、视图等;存储引擎层负责数据的存储和提取,MySQL5.5.5版本开始默认使用InnoDB,即你执行create table建表时,不指定引擎类型,默认使用InnoDB;
- 连接器:
- 连接管理(Connection Handling):当一个客户端进行连接服务端时,会得到一个server处理线程,每个连接的请求处理都是单线程的,同时服务器会缓存这些线程,所以当一个新的连接来时就不需要创建和销毁线程【MySQL5.5及其以上版本提供了一个支持线程池插件的接口】;
- 权限认证(Authentication):当客户端连接服务端时,服务端需要对连接进行认证,即对username、host、password进行认证;
- 安全(Securith):当客户端成功连接上服务端时,服务端会对每个连接查看它的系统权限清单【mysql> show privileges \G】,之后这个连接里面的权限判断逻辑,都将依赖于此时读到的权限,即一个用户成功建立连接后,即使对这个用户的权限做了修改,也不会影响到已经存在连接的权限,修改完后,只有再新建的连接才会使用新的权限设置;
- 备注:
- 连接完成后,如果没有后续的操作,这个连接就处于空闲状态,可以使用show processlist进行查看,当Command列中出现Sleep时表示该连接是空闲状态;客户端如果太长时间没有动静,连接器会自动断开连接,这个时间由参数wait_timeout控制,默认值是8小时,如果在连接被断开后,客户端再次发起请求,会收到一个错误提醒:Lost connection to MySQL server during query。这时候如果要继续,就需要重连,然后再执行请求;
- 数据库里面的长连接成功后,如果客户端持续有请求,则一直使用同一个连接;短连接则是每次执行完很少的几次查询就断开连接,下次查询再重新建立一个;
- 全部使用长连接后,有时候MySQL占用内存涨的很快,这是因为MySQL在执行过程中临时使用的内存是管理在连接对象中的,这些资源在断开时才会被释放,如果长连接累计下来,可能导致内存占用太大,被系统强行杀掉(OOM),从现象看就是MySQL异常重启了;
- 解决方案1:定期断开长连接。使用一段时间或程序里面判断执行过一个占用内存的大查询后,断开连接,之后要查询再重连;
- 解决方案2:MySQL版本如果是5.7及其以上,可以在每次执行一个大的操作后,通过执行mysql_reset_connection来重新初始化连接资源。这个过程不需要重连和做权限验证,会将连接恢复到刚刚创建完时的状态。
- 分析器(Parser):MySQL分析器会创建一个内部结构(解析树),MySQL的解析行为就像单趟编译器一样,进行词法解析、语法解析、语义解析;
- 词法解析:MySQL对语句进行识别里面的字符串分别是什么,代表什么,比如”select“是一个查询语句,吧字符串”tableName”识别为“表名 tableName”,吧字符串”id“识别成”列id”;
- 语法解析:根据语法规则,判断输入的SQL语句是否满足MySQL语法,比如“elect *from tableName”这个会提示”You hava an error in your SQL syntax“的错误提醒;一般语法错误会提示第一个出现错误的位置,所以要关注的是紧接”use near”的内容;
- 优化器(Optimizer):当创建完解析树后,服务端会进行一系列的优化操作,包括重写查询语句、确定读表的顺序、索引选择等等,你可以使用explain进行查看细节【MySQL笔记(3)– SQL分析】;
- 缓冲器(Caches):缓冲器会缓存查询的结果集,当进行查询解析前,服务端会去缓存器查找,如果改查询命中缓存,那就不需要进行解析、优化、执行等等操作,直接返回缓存结果集;【以key-value保存执行过的语句及查询结果,如果对表进行了更新操作,该表的所有查询缓存都会清空】
- 执行器:开始执行时,需要先判断你有没有这个表的执行权限,如果没有,返回没有权限的错误【同时对于命中查询缓存,会在查询缓存返回结果时做权限验证,查询会在优化器之前调用precheck验证权限】,如果有权限,打开表继续执行,执行器根据表的引擎定义,去使用这个引擎提供的接口,比如查询语句select *from table where id=1;中的id字段没有索引,那么执行器的执行流程是
- 调用InnoDB引擎接口取这个表的第一行,判断id是不是1,如果不是则跳过,如果是则将这行存在结果集中;
- 调用引擎接口取”下一行“,重复相同的判断逻辑,直到取到这个表的最后一行;
- 执行器将上述遍历过程中所有满足条件的行组成的结果集返回给客户端;
- 连接器:
版权声明:本文为huangrenhui原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。