体系结构
体系结构
Server 层
连接层:连接器
连接、授权认证
连接超上限:Too many connections
SHOW VARIABLES LIKE '%max_connections%'; set GLOBAL max_connections=500;
服务层
- 查询缓存(MySQL 8 移除,5.7 建议关闭)
- 解析器/分析器
- 优化器/查询优化器
- 执行器
存储引擎层
引擎层
可插拔存储引擎
实现:内存、索引和存储管理
存储层
- 系统文件
- 文件和日志
执行过程
执行一条 SQL 查询语句,期间发生了什么?
连接器:建立连接,管理连接、校验用户身份;
查询缓存:查询语句如果命中查询缓存则直接返回,否则继续往下执行。
MySQL 8.0 已删除该模块;
解析 SQL,通过解析器对 SQL 查询语句进行词法分析、语法分析,然后构建语法树,方便后续模块读取表名、字段、语句类型;
执行 SQL:
预处理阶段:
- 检查表或字段是否存在;
- 将
select *
中的*
符号扩展为表上的所有列。
优化阶段:基于查询成本考虑, 选择索引,产生查询成本最小的执行计划;
执行阶段:根据执行计划执行 SQL 查询语句,从存储引擎读取记录并返回;
查询过程
查询语句的执行流程如下:
权限校验(如果命中缓存)--->查询缓存--->分析器--->优化器--->权限校验--->执行器--->引擎
更新语句执行流程如下:
分析器---->权限校验---->执行器--->引擎---redo log(prepare 状态)--->binlog--->redo log(commit 状态)
权限校验的时机
连接器
命中缓存时
执行器、优化器完毕后
如果没有权限就会返回错误信息,如果有权限就会调用数据库引擎接口,返回引擎的执行结果。
更新语句涉及的两阶段提交
如果采用 redo log 两阶段提交的方式就不一样了,写完 binlog 后,然后再提交 redo log 就会防止出现上述的问题,从而保证了数据的一致性。
那么问题来了,有没有一个极端的情况呢?
假设 redo log 处于预提交状态,binlog 也已经写完了,这个时候发生了异常重启会怎么样呢? 这个就要依赖于 MySQL 的处理机制了,MySQL 的处理过程如下:
- 判断 redo log 是否完整,如果判断是完整的,就立即提交。
- 如果 redo log 只是预提交但不是 commit 状态,这个时候就会去判断 binlog 是否完整,如果完整就提交 redo log, 不完整就回滚事务。
这样就解决了数据一致性的问题。