MySQL基本架构示意图
如上图所示:MySQL分为两层
Server层
连接器、查询缓存、分析器、优化器、执行器等;
涵盖 MySQL 的大多数核心服务功能;
所有内置函数(日期、时间、数学、加密函数等);
所有跨存储引擎的功能都在这一层实现(存储过程、触发器、试图等);
存储引擎层
数据的存储和提取:
架构模式:支持InnoDB、myISAM、Memory等多个存储引擎。
最常用的存储引擎:InnoDB;
MySQL 5.5.5版本开始成为默认存储引擎;
不同的存储引擎共用一个 Server 层 - 连接器到执行器的部分;
连接器
首先连接到这个数据库上 - 这时接待你的就是 连接器;
负责跟客户段建立连接、获取权限、维持和管理连接
连接命令:
mysql -hsip -PSport -uSueser -p
连接命令中的MySQL是客户端工具,用来跟服务端建立连接。
完成经典的TCP握手后,连接器开始认证身份;
这时用的就是你输入的用户名和密码;
如果用户名 或 密码不对,你就会收到一个 “ Access denied for user ”的错误。然后客户端程序结束执行;
如果用户名 密码认证通过:
连接器会到权限表里面查出你拥有的权限。
之后,这个连接里面的权限判断逻辑,都将依赖于此时读到的权限。
一个用户建立成功后: 即使你用管理员账户对这个用户的权限做了修改,也不会影响已经存在连接的权限。 修改完成后只有在新建才会使用心得权限设置;
空闲状态:
连接完成后,如果没有后续的动作;
可以用命令:show processlist 来查看;
客户端如果太长时间没有动静,连接器就会自动将它断开。 这个时间由参数:wait_timeout控制。默认值:8小时;
长连接:
指连接成功之后,如果客户端有持续请求,则一直使用同一个连接。
短链接:
指每次执行完很少的几次查询就断开连接,下次查询再重新建立一个;
连接建议:
建立连接的过程通常时比较复杂的,建议尽量减少建立的动作,尽量使用长连接;
但是全部使用长连接后,MySQL占用内存涨得特别快。
因为MySQL在执行过程中临时使用的内存是管理在连接对象里面的。
这些资源汇总连接断开的时候才释放。
因此,长期连接累积下来。
可能导致内存占用太大,被系统强行杀掉(OOM);
现象:MySQL异常重启;
解决方案:
定期断开长连接。
使用一段时间,断开连接,之后要查询再重连;
MySQL5.7及后版本
可以在每次执行一个比较大的操作后,通过执行mysql_reset_connection来重新初始化连接资源。
这个过程不需要重连和重新做权限验证,
但是会将连接恢复到刚刚创建完成时的状态。
查询缓存
连接建立完成后,执行select语句。
执行逻辑来到第二步:查询缓存。
MySQL拿到一个查询请求后,会先到查询缓存看看,之前是不是执行过这条语句。
之前执行过的语句及其结果可能会以key - value 对的形式。被直接缓存在内存中。
key 是查询的语句,value 是查询的结果。
如果查询能够直接在这个缓存中找到key,那么这个value就会被直接返回给客户端。
如果语句不在查询缓存中,就会继续执行后面的执行阶段。
执行完成后,执行结果会被存入查询缓存中。
可以看到,如果查询命中缓存,MySQL不需要执行后面的复杂操作,就可以直接返回结果,这个效率会很高。
建议:
大多数情况不要使用查询缓存,因为查询缓存弊大于利;
查询缓存的失效非常频繁。
只要有对一个表的更新,这个表上所有查询缓存都会被清空。
尚未使用,就被一个更新全搞掉了 - 费力不讨好;
尤其是更新压力达的数据库来说。
适用于 静态表 - 很长时间才会更新一次。(比如往年的人口数据,一个系统的配置信息);
命令:
默认 SQL 语句都不使用查询缓存。
将参数 query_cache_type 设置成 DEMAND;
确定要使用查询缓存的语句
用 SQL_CACHE 显式指定
eg:
mysql> select SQL_CACHE * from T where ID=10;
MySQL 8.0版本直接将查询缓存的整块功能删掉了;之后没有这个功能了;
分析器
没有命中缓存,开始真正执行语句。
首先 - MySQL需要指点, 你要做什么,因此需要对 sql 语句做解析;
分析器先会做 “词法分析”
SQL语句:由多个字符串和空格组成;
MySQL 需要识别出里面的字符串分别是什么,代表什么。
MySQL 从输入的 “select” 这个关键字识别出来,这是个查询语句
它也需要把字符串 “ T ” 识别成 “ 表名T ",把字符串 “ ID ” 识别成 " 列 ID ".
做完 词法分析 识别后,做 “ 语法分析”
根据语法 分析的结果,
语法分析会根据语法规则,判断输入的这个 SQL 语句是否满足 MySQL语法;
优化器
MySQL 通过分析器知道要做什么。执行前要先经过优化器的处理
优化器
表里面有多个索引的时候,决定使用哪个索引;
或者在一个语句有多表关联(JoIN)的时候,决定几个表的连接顺序。
优化器使用效率搞的方案:
优化器阶段完成后,这个语句执行的方案就确定了,然后进去执行阶段;
执行器
MySQL
通过 分析器 知道 你要做什么
通过 优化器 知道 该怎么做
于是进入了 执行器 阶段,开始执行语句。
开始执行的时候
首先判断你对这个表 T 有没有执行查询的权限;
没有,返回没有权限的错误;
在工程实现中,如果命中缓存,会在查询缓存返回结果的时候,做权限验证;
查询也会在优化器之前调用 precheck 验证权限;
有权限 - 打开表继续执行
打开表的时候,执行器就会根据表的引擎定义,去使用引擎提供的接口