MySQL整体架构
从架构上来看,大致为Server层与存储引擎层。
Server层
主要包括连接器、查询缓存、分析器、优化器、执行器等,存储过程、触发器、视图和内置函数(如:时间、日期、数字等)都在这层实现。
存储引擎层
引擎层负责数据的提取与存储,如InnoDB、MyISAM、Memory等引擎。目前最常用的存储引擎是InnoDB,它从MySQL5.5版本开始作为默认存储引擎。像目前来说大部分应该都是MySQL5.5以上版本,故而都是InnoDB引擎
接下来重点分析连接器、查询缓存、分析器、优化器、执行器各自干了哪些事情。
连接器
负责和客户端建立连接,获取用户权限以及维持和管理连接。MySQL是开源的,它有非常多种类的客户端:navicat、mysqlfront、SQLyog等。发起通信都必须先跟Server端建立连接,而建立连接就是连接器完成。
1.连接到数据库,写法大致如下:
mysql -h host[数据库地址] -u root[用户名] -p root[密码] -P 3306[端口]
1.如果用户名或密码不正确,,你就会收到一个"Access denied for user"的错误,然后客户端程序结束执行。
2.如果用户名密码正确,连接器会在权限表查询当前用户所拥有的的权限.
也就是说,用户创建连接后,即使权限被管理员修改了,也不会影响已经存在的权限.修改完,只有重新新建的链接才会使用新的权限设置。权限表在系统表空间mysql的user表中。
通过 show processlist;
show processlist;
结果如下:
来查询连接的状态。在用户建立连接后,即使管理员改变连接用户的权限,也不会影响到已连接的用户。默认连接时长为 8 小时,超过时间后将会被断开。
简单说下长连接:
优势:在连接时间内,客户端一直使用同一连接,避免多次连接的资源消耗。
劣势:在 MySQL 执行时,使用的内存被连接对象管理,由于长时间没有被释放,会导致系统内存溢出,被系统kill. 所以需要定期断开长连接,或执行大查询后,断开连接。MySQL 5.7 后,可以通过 mysql_rest_connection 初始化连接资源,不需要重连或者做权限验证。
查询缓存
当接受到查询请求时,会现在查询缓存中查询(key/value保存),是否执行过。没有的话,再走正常的执行流程。
但在实际情况下,查询缓存一般没有必要设置。因为在查询涉及到的表被更新时,缓存就会被清空。所以适用于静态表。在 MySQL8.0 后,查询缓存被废除
分析器#
词法分析: 如识别 select,表名,列名,判断其是否存在等。 分析过程如下:
语法分析: 判断语句是否符合 MySQL 语法。
SQL语句的分析分为词法分析与语法分析,mysql的词法分析由MySQLLex[MySQL自己实现的]完成,语法分析由Bison生 成。关于语法树大家如果想要深入研究可以参考这篇wiki文章:en.wikipedia.org/wiki/LR_par… 外,Java当中也有开源的词法结构分析工具例如Antlr4,ANTLR从语法生成一个解析器,可以构建和遍历解析树,可以在IDEA 工具当中安装插件:antlr v4 grammar plugin。插件使用详见课程
经过bison语法分析之后,会生成一个这样的语法树
优化器
确定索引的使用,join 表的连接顺序等,选择最优化的方案。 优化可参阅之前的文章。
执行器
开始执行的时候,要先判断一下你对这个表 T 有没有执行查询的权限,如果没有,就会返回没有权限的错误,如下所示 (在 工程实现上,如果命中查询缓存,会在查询缓存返回结果的时候,做权限验证。查询也会在优化器之前调用 precheck 验证权 限)。
select * from test where id=1; 如果有权限,就打开表继续执行。打开表的时候,执行器就会根据表的引擎定义,去使用这个引擎提供的接口。 比如我们这个例子中的表 test 中,ID 字段没有索引,那么执行器的执行流程是这样的:
1.调用 InnoDB 引擎接口取这个表的第一行,判断 ID 值是不是 10,如果不是则跳过,如果是则将这行存在结果集中;
2.调用引擎接口取“下一行”,重复相同的判断逻辑,直到取到这个表的最后一行。
3.执行器将上述遍历过程中所有满足条件的行组成的记录集作为结果集返回给客户端。
至此,这个语句就执行完成了。对于有索引的表,执行的逻辑也差不多。