整体框架结构
Service层
作用:涵盖MySQL的大多数核心功能,以及所有的内置函数,所有跨存储引擎的功能(存储过程、触发器、视图)
包含:
连接器:
- 负责跟客户端建立连接、获取权限、维持和管理连接
- 连接命令:mysql -h $ip -P $port -u $user -p
查询缓存:
大多是情况下不会使用查询缓存,因为查询缓存往往弊大于利。查询缓存的失效很频繁,只要有对一个表的更新,这个表上所有的查询缓存都要被清空。除非是一个系统配置表,不经常更新才适合使用查询缓存。所以MySQL8.0版本直接把查询缓存的整块功能删掉了。
分析器
优化器:
- 在表里有多个索引的时候,决定使用哪个索引;
- 或者在一个语句有多表关联的时候,决定各个表的连接顺序;
- 或者先从from开始执行,on等顺序。我们想的手写的sql语句执行书序不同
执行器
数据库尽量使用长连接,但是有些时候MySQL占用的内存涨的特别快,导致MySQL异常启动了?
原因:MySQL执行过程临时使用的内存是管理在连接对象里面的。这些资源会在断开连接的时候才释放。所以长连接积累下来,可能会导致内存占用太大,被系统强行杀掉。
解决:
- 定期断开长连接之后重连。
- 5.7以后的版本可以使用mysql_reset_connection来重新初始化连接的资源,这个过程不需要重连和重新进行权限验证。
存储引擎层:
负责数据的存储与提取。其架构模式是插入式的,支持InnoDB、MyISAM等多个存储引擎。
查询语句的执行过程一般是经过连接器、分析器、优化器、执行器等功能模块,最后到达存储引擎。更新语句的执行流程还涉及两个日志模块
日志模块
前提:
- MySQL如果每次更新操作都需要写入磁盘中,然后磁盘也要找到对应的那条记录,然后更新,整个过程的IO成本、查询成本都很高。
- 为了解决这个问题,使用WAL技术:也就是先写入日志,再写入磁盘。
- 比如:InnoDB引擎就会将记录写到redo log日志中,并更新内存,这个时候就算更新完成。同时会在系统比较空闲的时候或者redo log日志容量满的时候,将日志里面的操作记录更新到磁盘里面。
redo log日志(重做日志):
- crash-safe(宕机安全):有了redo log日志就会保证即使数据库异常重启,之前提交的记录都不会丢失的能力。
- 物理日志:记录的是:“在某数据页上做了什么修改”。
- 循环写,大小固定、环装的存储结构
binlog日志(归档日志):
- 在MySQL的server层实现的,只能用于归档。
- 逻辑日志,记录的是:这个原句的原始逻辑,比如:“给ID = 2这一行的c字段加一”。
- 可以追加写,指的是binlog文件写到一定大小后会切换到下一个,不会覆盖以前的日志。
补充:
为什么不能去掉binlog日志、只留下redo log日志?
- redo log日志只有InnoDB引擎有,别的引擎没有。binlog日志存在于MySQL的server层。
- redo log日志是循环写,不能持久保存,没有binlog日志归档的功能。
- 主从复制都是基于binlog日志进行复制的。
为什么需要redo log日志?
因为里面保存的是未被刷新到磁盘的日志,而binlog日志是全部的信息,没有字段区分哪些是宕机之前的还是之后的,只能用于归档。
两阶段提交
前情提要:如果直接先执行binlog日志、后执行redo log日志或者反之都会出现数据丢失的情况(只要一个日志有数据另一个没有),所以需要预处理准备状态;
具体步骤:
- 将修改的数据,同构InnoDB引擎将数据保存到内存中,同时记录redo log日志;
- redo log进入prepare(准备)状态,接着执行执行器;
- 执行器通知binlog记录更改信息;
- 提交redo log日志;
补充:可能会遇到的情况:
1. 准备redolog,机器异常重启。会根据redolog的完整性,如果完整。立即提交,之后恢复数据。保证了数据库的持久性
2.
准备redolog,之后binlog,机器异常重启。会判断binlog的完整性。如果完整,redolog立刻提交。恢复数据,redolog和binlog都有记录。从而保证了数据的一致性。如果binlog不完整,进行事务回滚。需要重新执行sql语句。从而保证数据的一致性。