![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/e095df627d4cad8b6471f0128df858d8.png)
基本架构
服务层
涵盖了mysql的大多数核心服务功能,所有的跨存储引擎的功能都在这层实现,例如存储过程、触发器、视图
连接器
负责跟客户端建立连接,获取用户权限,维持和管理连接
客户端发起连接请求,先进行TCP握手,连接器就开始认证身份,若用户名和密码不对则返回错误,客户端执行结束。
用户名和密码验证通过,连接器到权限表中获取拥有的权限,之后连接里面的权限判断都依赖此时读取的权限
当连接完成之后,当前连接处于空闲状态,可以使用show processlist
命令查找
客户端长时间无请求,连接器会主动断开,通过wait_timeout
控制,默认8小时
查询缓冲
之前执行过的语句会以k-v的形式存放在内存中,mysql得到一个查询请求,会先在缓冲中查找,是否之前被执行过
查询缓冲弊大于利,当一个表更新之后,表上原有的查询会被清空,如果是相对更新频率比较低的表做缓冲比较划算,MySQL8之后废除整个缓存功能
分析器
词法解析:解析sql语句,识别出语句的成分,例如查询语句还是更新语句
语法解析:先判断语法是否符合MySQL的语法规则,包括是列是否存在,表是否存在
优化器
生成执行计划,决策使用的索引,多表关联的连接顺序
执行器
首先会在优化器之前先校验对表是否有对应得操作执行权限,后续执行器打开表,根据表得引擎定义,使用对应得引擎接口,最终把结果返回客户端
执行引擎层
存储和读取数据,提供读写接口,引擎内部的逻辑,例如查询的优化,使用索引定位磁盘数据,事务支持
客户端
负责跟服务端建立连接,发送执行语句,接受执行结果
日志模块
重做日志 redo log
由innodb引擎实现
redo log
是物理日志,记录的是在某数据页上做了什么修改,当有一条记录更新的时候,innodb先把记录对应的所在页的改动写到redo log里面,并更新内存数据,此时就算更新完成。同时innodb引擎会在适当的时候比如系统比较空闲的时候,更新到磁盘。- 每个文件默认1G,一组4个文件,从文件头部开始写,到末尾再从头循环
write pos
是当前记录的位置,一边写一边向后移动,当写到3号文件末尾后回到0号文件头
4.checkpoint
是当前要擦除的位置,也是往后移动并且循环,擦出记录前更新到数据文件中- 有了redo log,innodb就可以保证数据库发生异常重启,之前提交的记录不会丢失,称之为
crash-safe
WAL(write-ahead loggin)技术:
先写日志,再写磁盘
innodb把内存中变更的数据页flush到磁盘中
- 脏页:内存中的数据页跟磁盘中的数据页不一致称为
脏页
- innodb刷新脏页到磁盘的策略
- 参数
innodb_io_capacity
限制磁盘的负载能力,这个值可以设置为磁盘的IOPS
- IOPS通过
fio
工具获取: fio-direct=1 -iodepth 1 -thread -rw=randrw -ioengine=psync -bs=16k -size=500M -numjobs=10 -runtime=10 -group_reporting -name=mytest innodb_flush_neighbors
默认为1,表示当前页刷新到磁盘时,如果旁边的数据页也是脏页,则把旁边的脏页也一起刷新掉,这个逻辑有顺延的效果
- 参数
回滚日志 undo log
由innoDB引擎实现,是事务的回滚日志,主要记录某数据被修改之前的日志,包括数据页的变更和change buffer的变更,每次数据被修改之前记录到undo log中,当需要回滚到某个版本时,可以通过undo log完成
分类
- insert undo log :实现在插入新的记录产生的undo log,当事务提交之后可以直接丢弃
- update undo log:事务在进行update/delete时产生的undo log,在快照读时还是需要的,所以不能直接删除,只有当系统没有比这个log更早的read-view的时候才可以删除
用途
- 保证事务进行roolback的时候的原子性和一致性,当事务回滚时可以可以使用undo log的数据进行恢复
- 用户MVCC快照的数据,在MVCC多版本控制中,通过读取undo log的历史版本数据可实现不同事务版本号拥有自己的独立的快照数据版本
归档日志 binlog
server层实现
- binlog是逻辑日志,记录的是这个语句的原始逻辑
- binlog可以持续追加,通过参数配置单个binlog文件的最大大小,和保存的最大个数
- 可通过binlog恢复被误修改的数据,同时也是作为主从复制的重要文件
机制
事务执行过程中,先把日志写入binlog cahce,事务提交的时候,再把binlog cache写到binlog文件中,并清空binlog cache
一个事务的binlog不能被拆开,不管这个事务多大,都不会被一次性写入
参数binlog_cache_size
可以控制每一个线程内的binlog cache的内存大小,超过该值,暂存磁盘
参数sync_binlog
控制刷盘时机
- 0,每次事务提交只write,不进行fsync
- 1,默认值,每次事务都执行fsync
- N,>1 每次事务提交都write 累积到N个事务才fsync
- 常见的会设置为100-1000中的一个数值,对应的风险是:如果主机发生异常重启,会丢失最近N个事务的binlog日志
三种格式
- Row level:保存每行被修改的细节,任何情况下都可以进行数据恢复,加快从库重放日\志的效率,保证从库数据的一致性
- Statement level:每条修改数据的sql会被记录下来,可能这条语句影响多行数据,对于Row模式下就是多行binlog
- Mixed level:混合模式
作用
主从复制:master端开启binlog,master把二进制日志传递给salve并回收
数据恢复:通过MySQLbinlog工具可以恢复数据
增量备份
两阶段性提交
redo log 的写入被拆成了两个步骤, prepare 和 commit 两步; 当redo log经历了这两个步骤才算更新完成, 最终保证数据的一致性
分析两种crash场景
-
- 在“写入redolog”后“写binlog”前 发生crash
此时binlog还没有写,redolog也还没有提交,所以在恢复的时候, 这个事物会回滚
- 在“写入redolog”后“写binlog”前 发生crash
-
- 在“写binlog” 后, redlog 还没有commit 前发生crash
如果redolog事物是完整的,同时已经有了commit标识, 则直接提交; 如果redolog事务只有完整的prepare, binlog完整则提交事物,如果binlog不完整则回滚事务
- 在“写binlog” 后, redlog 还没有commit 前发生crash
binlog完整性判断规则
- statment格式的binlog,最后都要commit
- row格式的binlog,最后会有一个XID event
- MySQL5.6之后,引入binlog-checksum参数可以验证binlog的正确性