MYSQL:连接器、查询缓存、解析SQL
MySQL 是什么MySQL是一个开源关系型数据库管理系统。核心特点使用SQLClient / Server 架构高性能支持事务支持多存储引擎MySQL 用来 存数据 查数据 管理数据 的软件例如idnameage1Tom202Alice18数据库就是一堆这种表MySQL 整体架构MySQL 的架构共分为两层Server 层和存储引擎层Server 层负责建立连接、分析和执行 SQL。MySQL 大多数的核心功能模块都在这实现主要包括连接器查询缓存、解析器、预处理器、优化器、执行器等。另外所有的内置函数如日期、时间、数学和加密函数等和所有跨存储引擎的功能如存储过程、触发器、视图等。都在 Server 层实现。存储引擎层负责数据的存储和提取。支持 InnoDB、MyISAM、Memory 等多个存储引擎不同的存储引擎共用一个 Server 层。现在最常用的存储引擎是 InnoDB从 MySQL 5.5 版本开始 InnoDB 成为了 MySQL 的默认存储引擎。我们常说的索引数据结构就是由存储引擎层实现的不同的存储引擎支持的索引类型也不相同比如 InnoDB 支持索引类型是 B树 且是默认使用也就是说在数据表中创建的主键索引和二级索引默认使用的是 B 树索引。连接器作用管理客户端连接连接的过程需要先经过 TCP 三次握手因为 MySQL 是基于 TCP 协议进行传输的如果 MySQL 服务正常运行完成 TCP 连接的建立后连接器就要开始验证你的用户名和密码如果用户名或密码不对就收到一个Access denied for user的错误然后客户端程序结束执行。如果用户密码都没有问题连接器就会获取该用户的权限然后保存起来后续该用户在此连接里的任何操作都会基于连接开始时读到的权限进行权限逻辑的判断。所以如果一个用户已经建立了连接即使管理员中途修改了该用户的权限也不会影响已经存在连接的权限。修改完成后只有再新建的连接才会使用新的权限设置。如何查看 MySQL 服务被多少个客户端连接了如果你想知道当前 MySQL 服务被多少个客户端连接了你可以执行show processlist命令进行查看。MySQL 的连接数有限制吗MySQL 服务支持的最大连接数由 max_connections 参数控制比如我的 MySQL 服务默认是 151 个,超过这个值系统就会拒绝接下来的连接请求并报错提示“Too many connections”。怎么解决长连接占用内存的问题有两种解决方式。第一种定期断开长连接。既然断开连接后就会释放连接占用的内存资源那么我们可以定期断开长连接。第二种客户端主动重置连接。MySQL 5.7 版本实现了mysql_reset_connection()函数的接口注意这是接口函数不是命令那么当客户端执行了一个很大的操作后在代码里调用 mysql_reset_connection 函数来重置连接达到释放内存的效果。这个过程不需要重连和重新做权限验证但是会将连接恢复到刚刚创建完时的状态。至此连接器的工作做完了简单总结一下与客户端进行 TCP 三次握手建立连接校验客户端的用户名和密码如果用户名或密码不对则会报错如果用户名和密码都对了会读取该用户的权限然后后面的权限逻辑判断都基于此时读取到的权限查询缓存连接器的工作完成后客户端就可以向 MySQL 服务发送 SQL 语句了MySQL 服务收到 SQL 语句后就会解析出 SQL 语句的第一个字段看看是什么类型的语句。如果 SQL 是查询语句select 语句MySQL 就会先去查询缓存 Query Cache 里查找缓存数据看看之前有没有执行过这一条命令这个查询缓存是以key-value形式保存在内存中的key 为 SQL 查询语句value 为 SQL 语句查询的结果。如果查询的语句命中查询缓存那么就会直接返回 value 给客户端。如果查询的语句没有命中查询缓存中那么就要往下继续执行等执行完后查询的结果就会被存入查询缓存中。这么看查询缓存还挺有用但是其实查询缓存挺鸡肋的。对于更新比较频繁的表查询缓存的命中率很低的因为只要一个表有更新操作那么这个表的查询缓存就会被清空。如果刚缓存了一个查询结果很大的数据还没被使用的时候刚好这个表有更新操作查询缓冲就被清空了相当于缓存了个寂寞。解析 SQL解析器解析器会做如下两件事情。第一件事情词法分析。MySQL 会根据你输入的字符串识别出关键字出来例如SQL语句 select username from userinfo在分析之后会得到4个Token其中有2个Keyword分别为select和from关键字 非关键字 关键字 非关键字selectusernamefromuserinfo第二件事情语法分析。根据词法分析的结果语法解析器会根据语法规则判断你输入的这个 SQL 语句是否满足 MySQL 语法如果没问题就会构建出 SQL 语法树这样方便后面模块获取 SQL 类型、表名、字段名、 where 条件等等。如果我们输入的 SQL 语句语法不对就会在解析器这个阶段报错。比如我下面这条查询语句把 from 写成了 form这时 MySQL 解析器就会给报错。但是注意表不存在或者字段不存在并不是在解析器里做的《MySQL 45 讲》说是在解析器做的但是经过我和朋友看 MySQL 源码5.7和8.0得出结论是解析器只负责检查语法和构建语法树但是不会去查表或者字段存不存在。