基础架构
- MySQL可以分为Server层、存储引擎层两部分。
- Server层包括:
- 连接器
- 查询缓存
- 分析器
- 优化器
- 执行器
- 内置函数(日期、时间等)
- 引擎存储层:负责数据的存储和提取,架构模式是插件式的。
- InnoDB
- MyISAM
- Memory
不同存储引擎的表存取方式不同,支持的方式也不同,但所有的存储引擎公用一个server层。
Service层
连接器
- 连接器负责跟客户端建立连接、获取权限、维持和管理连接。
连接命令
mysql -h$ip -P$port -u$user -p
- 如果用户名或密码错误,将会收到一个"Access denied for user"的错误,然后客户端程序结束执行。
- 如果通过,连接器回到权限表里面查出本用户所拥有的权限。之后,这个链接里面的权限判断逻辑都会依赖与读到的权限。
这就意味着,一个用户成功建立连接后,即使你用管理员账号对这个用户的权限做了修改,也不会影响已经存在连接的权限。
修改完成后,只有再新建的连接才会使用新的权限设置。连接完成后,如果你没有后续的动作,这个连接就处于空闲状态,你可以在 show processlist 命令中看到它。文本中这个图是 show processlist 的结果,其中的 Command 列显示为“Sleep”的这一行,就表示现在系统里面有一个空闲连接。
- 客户端如果太长时间没有操作,连接器会自动将它断开,这是时间由参数wait_timeout控制,默认是8小时。
数据库中,长连接是指连接成功后,如果客户端持续有请求,则一直使用同一个连接,短连接则是指每次执行完很少的几次查询后就断开连接,下次拆线呢重新创建一个。
- 异常:
- 在全是使用长连接后,有些MySQL占用内存涨的特别快,这是因为MySQL在执行过程中临时使用的内存是管理在连接对象里面的。这些资源会在连接断开的时候释放。所以长连接持续积累就会导致内存占用太大,被系统强行Kill掉(OOM)。
- 解决:
- 定期断开长连接。使用一段时间,或者程序里面判断执行过一个占用内存的大查询后,断开连接,之后要查询再重连。
- 在MySQL 5.7或之后的版本,可以在执行一个比较大的操作之后,通过执行++mysql_reset_connection++来重新初始化连接资源。这个过程不需要重连和重新做权限验证,但是会恢复到刚刚创建完时的状态。
查询缓存
- MySQL拿到一个查询后会先到查询缓存中查询。之前执行的语句及其结果以Key-Value对的形式,被直接缓存在内存中。key是查询的语句,value是查询的结果。
- 如果没有缓存,则进行下一步操作。
大多情况下不建议使用缓存
- 查询缓存失效频繁,只要一个表有更新,所有缓存都会情况。缓存一般适用于静态表,长时间才更新一次。
- MySQL可以指定SQL语句查询使用缓存。
- MySQL8.0将缓存功能删除。
分析器
- 分析器对SQL语句进行解析,进行“词法分析”,提取出关键字,它也要把字符串T”识别成“表名 T”,把字符串“ID”识别成“列 ID”。
优化器
- 优化器是在表里有多个所有时,巨大使用那个索引。
- 一个语句有多表关联(join)的时候,决定各个表的连接顺序.
mysql> select * from t1 join t2 using(ID) where t1.c=10 and t2.d=20;
既可以先从表t1里面取出c = 10的ID值,根据ID值关联到t2,再判断t2里面d的值是否等于20.
先从t2里面取出d = 20的ID值,再根据ID值关联到t1,再判断t1里面C的值是否等于10.
两个执行逻辑结果一样,但是执行效率不同,优化器就是要决定使用哪一个方案。
执行器
- 开始执行的时,先判断对这个表是否有查询的权限。
- 有权限则打开表执行,打开表的时候,执行器会根据表的引擎定义。去使用这个引擎提供的接口。
执行流程:
- 调用InnoDB引擎接口取这个表的第一行,判断ID值是不是10,如果不是则跳过,如果是则将这行存在结果集中。
- 调用引擎接口取“下一行”,重复相同的逻辑判断,直到取到这个表的最后一行。
- 执行器将上述执行的结果组成记录集返回给客户端。
- 慢查询日志中会看到rows_examined的字段,表示这个语句执行过程中扫描了多少行。
思考
- 分析器阶段: 做词法分析后做语法分析,词法分析主要做的是根据mysql的关键字进行验证和解析,而语法分析会在词法解析的基础上进一步做表名和字段名称的验证和解析,在此阶段会报出SQL语句错误。