Mysql的架构设计
Mysql分为Server层和存储引擎层:
Server层
主要包括连接器、查询缓存、分析器、优化器、执行器等,涵盖 MySQL 的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图等。
存储引擎层
存储引擎层负责数据的存储和提取。其架构模式是插件式的,支持 InnoDB、MyISAM、Memory 等多个存储引擎。现在最常用的存储引擎是 InnoDB,它从 MySQL 5.5.5 版本开始成为了默认存储引擎。也就是说如果我们在create table时不指定表的存储引擎类型,默认会给你设置存储引擎为InnoDB。
server层的执行过程:
连接器
首先连接器会判断该用户提交的SQL是否有权限,如果有权限才会进行后续的执行操作,连接器负责跟客户端建立连接、获取权限、维持和管理连接。
查询缓存
对于有相同查询条件的请求会在查询缓存中判断是否有之前请求的缓存结果。之前执行过的语句及其结果可能会以 key-value 对的形式,被直接缓存在内存中。key 是查询的语句,value 是查询的结果。如果你的查询能够直接在这个缓存中找到 key,那么这个 value 就会被直接返回给客户端。如果语句不在查询缓存中,就会继续后面的执行阶段。执行完成后,执行结果会被存入查询缓存中。可以看到,如果查询命中缓存,MySQL 不需要执行后面的复杂操作,就可以直接返回结果,这个效率会很高。
分析器
如果本次请求没有缓存命中,在分析器中用以进行词法和语法的分析,如果不符合规范则会抛出异常。
优化器
词法语法分析正常的话会进行优化器处理,在这个阶段会进过成本代价分析后,选择合适的索引。
执行器
最后调用选择的存储引擎来进行数据的查询和更新等操作。
InnoDB存储引擎的执行过程
- 执行一句SQL,先从考虑从内存中的buffer pool加载所需的记录数据,如果buffer pool没有相关数据,就会从磁盘中将包含该记录的页加载到buffer pool中来;
- 在buffer pool中将记录旧值写到undo log中,undo log是InnoDB存储引擎特有的日志类型,防止SQL执行失败需要回滚数据,如果失败直接从undo log中恢复即可;
- 在buffer pool中将旧值更新为新值,并将新值写入到redo log中,undo log也是InnoDB存储引擎特有的日志类型,防止SQL执行的结果还没有刷盘到磁盘中数据库服务crash掉,如果这样可以从undo log中重做;
- 将SQL执行的操作信息写入到binlog中,binlog按时刷盘写入到磁盘中,binlog是server层的机制,任何存储引擎都存在的机制;
- SQL执行完成;
undo log和redo log
- redo log是重做日志。保存的是一个事务T在进行X操作后的新值N,可以表示为:,是innodb存储引擎特有的,支持crash之后恢复没有刷盘的数据恢复。
- undo log是回退日志。保存的是一个事务T在进行Y操作后的老值O,可以表示为:,是innodb存储引擎特有的,支持事务失败后进行事务回滚。
binlog
- bin日志是mysql运行的日志,里面记录了mysql运行的操作,他是在server层实现的日志。保存的是逻辑日志,即保存的是sql语句,通过bin 日志做数据恢复。也可以保存实际的数据格式。
buffer pool
mysql执行一句更新操作的数据不会立即写入磁盘,会先放到buffer pool中,这是内存中的一片暂存区,等一段时间会刷入磁盘中。这样设计的作用是提高读写数据的效率。
WAL机制
WAL是先写日志再进行刷盘操作,就是会先将操作写入到redo log+binlog中,再将buffer pool中数据刷入磁盘;这样做的优势是:(1)保障数据不会丢失。及时数据服务crash,也能从redo log中进行恢复;(2)由于刷盘操作是顺序操作,相对于随机写的效率会高很多;(3)实际修改先写入buffer pool中,等内存满了在刷盘,这样明显降低了IO次数,提升了IO效率。
参考资料:
MySQL的内部组件结构:https://note.youdao.com/ynoteshare/index.html?id=f030268c54f18d2116837f8f3ef045bf&type=note&_time=1693637410183