0. MySQL的基础架构图:
(图片来自极客时间:https://time.geekbang.org/column/article/68319)
大体来说,MySQL可以分为Server层(服务器层) 和 存储引擎层 两部分。
Server层 包括 连接器、查询缓存、分析器、优化器、执行器等,涵盖MySQL的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等。
而 存储引擎层 负责数据的存储和提取。其架构模式是插件式的,支持InnoDB、MyISAM、Memory等多种存储引擎。现在最常用的存储引擎是 InnoDB,它从MySQL 5.5.5 版本开始成为了默认存储引擎。
从图中不难看出,不同的存储引擎共用一个Server层,也就是从连接器到执行器的部分。
下面依次看下每个组件的作用。
1. 连接器:
客户端如果太长时间没动静,连接器就会自动将其断开。
这个时间是由参数 wait_timeout 控制的,默认值是8小时。
mysql> show global variables like "%timeout";
+---------------------+-------+
| Variable_name | Value |
+---------------------+-------+
| interactive_timeout | 28800 |
| wait_timeout | 28800 |
+---------------------+-------+
如果在连接被断开之后,客户端再次发起请求的话,就会收到一个错误提醒:
Lost connection to MySQL server during query.
这时候如果你要继续,就需要重连,然后再执行请求。(mysql_ping + reconnect_opt)
由于连接建立的过程复杂且开销大,一般建议使用长连接。而长连接有一个问题就是MySQL在执行过程中临时使用的内存都会存放到连接对象中,长时间不释放持续累积会导致内存占用过大。
解决方式是:
客户端主动定期断开长连接,或者执行一个占用内存的大查询后断开连接再重连:
调用执行 ‘mysql_reset_reconnection’ 来重新初始化连接资源,无需重连、无需权限验证,会使连接恢复到新建完成时的状态。
int mysql_reset_connection(MYSQL *mysql);
2.查询缓存:
查询缓存弊大于利,查询缓存的失效非常频繁,只要有对一个表的更新,这个表上所有的查询缓存都会被清空。除非你的业务就是一张静态表,很长时间才会更新一次。
可以将参数 ‘query_cache_type’ 设置成 DEMAND,这样对于默认的SQL语句都不使用查询缓存,而对于你确定要使用查询缓存的语句可以使用 ‘SQL_CACHE’ 显式指定:
mysql> select SQL_CACHE * from T where ID = 10;
MySQL 8.0 版本 直接将查询缓存的整块功能删掉了,也就是说 8.0 开始彻底没有这个功能了。
3.分析器:
分析器:通过分析器 知道要做什么。
分析器 先做 “词法分析”,再做“语法分析”,“词法分析”将select等关键字从你输入的字符串中识别出来,再识别出表名、列名 等;“语法分析”检查输入的语法是否有错误,例如“select”输入成了“elect”。
4.优化器:
优化器:通过优化器知道 该怎么做。
当表里有多个索引时,优化器决定使用哪个索引;
或者当一个语句有多表关联(join)的时候,决定各个表的连接顺序。
select * from t1 join t2 using(ID) where t1.c = 10 and t2.d = 20;
5.执行器:
开始执行的时候,要先判断一下你对这个表是否有执行查询的权限。
select * from T where ID = 10;
执行过程是这样的:
如果这个表没有索引,则执行器调用 存储引擎的 ‘取下一行’ 接口,取出数据后判断ID的值是否等于10,如果不是则跳过,如果是则将这行存入到结果集中,重复调用存储引擎的接口取下一行,直到取到这个表的最后一行。
如果这个表有索引,则执行器调用存储引擎的 ‘取满足条件的第一行’ 接口,之后循环调用 ‘取满足条件的第一行’ 接口,这些都是存储引擎中已经定义好的。