整体框架
MySQL 可以分为 Server 层和存储引擎层(Storage Engines)两部分
Server 层
Server 层包括连接器、查询缓存、分析器、优化器、执行器等,涵盖了Mysql的大多数核心服务功能,以及内置函数,存储过程,触发器,试图等(所有的跨存储以前宁的操作)
Storage Engines层
主要是负责数据的存储和提取,其架构模式是插件式的,支持InnoDB,MyISAM,Memory等多个存储引擎。InnoDB是最常用的,也是Mysql5.5.5版本开始成为默认的存储引擎
连接器
- 负责维护客户端的链接,获取权限,管理链接
- 如果你没有后续的动作,这个连接就处于空闲状态(show processlist查看所有链接)
- 客户端如果太长时间没动静,连接器就会自动将它断开。这个时间是wait_timeout来控制的,默认8小时
- 短链接:每次完成执行都断开链接(建立链接的过程比较耗时,建议尽量使用长链接)
- 长连接:客户端维持请求一直使用一个链接(但是全部使用长链接会导致内存使用过快)
- 解决长链接内存过大的问题:Mysql5.7之后,可以每次执行一个较大的操作后,执行mysql_reset_connection开重新初始化链接资源,此过程无需重连和权限校验
查询缓存
MYSQL查询一个请求会先看查询缓存是否存在,之前执行过的缓存会已KV的形式存储在内存中,如果有则直接返回,但是默认建议不开启查询缓存,因为查询缓存失效频率太高,只要对一个表进行更新,那么这个表上所有的查询缓存都会被清空。mysql8.0已经将查询缓存整个删除了
分析器
分析器分析SQL语句进行语法分析,如果判断语法不对则会返回"You have an error in your SQL syntax" 的错误提醒
优化器
在经过分析器判断语法正确后,需要通过优化器进行优化处理,优化器是在表中存在多个索引的时候,决定使用哪个索引,或者在一个语句有多表关联查询(join)的时候决定表的链接顺序
执行器
用于语句执行
- 先判断你有没有这个表的执行查询的权限,没有返回权限错误的信息
- 根据引擎提供额执行接口执行语句查询
常用引擎,区别对比
引擎 | Innodb | Myisam |
---|---|---|
存储文件 | .frm 表定义文件 .ibd 数据文件 |
.frm 表定义文件 .myd 数据文件 .myi索引文件 |
锁表 | 表锁、行锁 | 表锁 |
事物 | ACID | 不支持 |
CRUD | 读、写 | 读多 |
count | 扫表 | 专门存储的地方 |
索引结构 | B+Tree(聚集索引) | B+Tree(非聚集索引) |
版本默认 | 5.7版本之后的默认引擎 | 5.7版本之前的默认引擎 |
一条查询语句是如何执行的
上述MYSQL各个模块的顺序就是一条查询语句的执行顺序
- 连接器创建客户端与服务器之间的链接
- 首先查询是否有查询缓存如果有则直接使用
- 如果没有查询缓存则到达分析器进行SQL语句的语法分析
- 确认语法无误之后,通过优化器进行查询优化
5.最终通过执行器调用引擎执行查询
一条更新语句是如何执行的
1.将ID为2的一条数据+1
- 执行器查询ID = 2的之一行,ID是逐渐,引擎使用B树搜索找到这一行,如果ID=2这一行数据在内存中(change buffer中),则直接返回给执行器,否则需要从磁盘读取到内存中。
- 执行器拿到行数据进行+1操作。再调用引擎写入新数据
- 引擎将这行数据更新到内存中,同时将这个数据记录到redo log中,此时redo log 处于prepare状态。然后告知执行器完成,随时可以提交数据
5.执行器生成操作的binlog,并把binlog写入磁盘
6.执行器调用引擎的提交事务接口,引擎把刚刚写入的redo log改成提交状态更新完成
过程中涉及到的几个角色,主要是涉及到redo log(重做日志)和 binlog(归档日志)这两个模块
redo log
如果每一次的更新操作都需要写进磁盘,然后磁盘也要找到对应的那条记录,然后更新,整个过程IO成本过高,为了解决上述问题,可以通过WAL技术来实现(Write-Ahead Logging),原理是,当有一条更新记录的时候,innodb先将操作记录到redo log中,并更新内存change buffer ,这个时候更新就完成了,然后Innodb会在是到的时候将操作记录更新到磁盘中,往往是系统比较空闲,或者change buffer 写满,或者redo log写满的时候
- redo log 是[固定大小的,一组四个文件,每个文件1G大小
- 有了redo log,innodb可以保证数据库异常数据也不丢失,保证了数据的原子性
binlog
上述说的redo log是innodb引擎特有的,而binlog则是Server层自己的日志,又称归档日志。为什么有两个日志,因为MYSQL之前没有innodb引擎。而且binlog只用于归档。他们有一下不同
- redo log是innodb特有的,而binlog是mysql的server层实现的,所有引擎都可以使用
- redo log 是物理日志,记录数据也上做了什么修改 ,binlog是逻辑日志,记录这个语句的原始逻辑"比如给ID=2 这一行的c字段加一"
- redo log 是循环写的,空间固定用完会刷新到磁盘,而binlog是最追加写入的
网友评论