学习MySQL的三大日志

执行一条select语句要经过的步骤

  1. 连接器
    • 与客户端进行TCP三次握手进行连接
  2. 查询缓存
    • MySQL8.0以后就将这部分给删掉了
  3. 解析SQL
    • 词法分析(分析出Token和KeyWard(select和from等))
    • 语法分析根据语法规则判断出MySQL语句如果没问题会构建出SQL语法树,如果语法不对会报错(from写成form)
    • 但是表不存在或字段不存在不是在这检测出的
  4. 执行SQL
    • 预处理
      • 在这个阶段会检测出表不存在或者字段不存在等错误
    • 优化器
      • 如果查询时可以选择多个索引,那优化器会基于成本考虑去选择一个合适的执行方案
    • 执行器
      • 按照优化器选择的执行方案去执行SQL语句,从存储引擎读取记录返回给客户端

执行一条update语句

执行update的操作也会发生执行select的操作,但是新增了

  1. 去buffer Pool读取数据
    • 如果读取到,直接返回个执行器
    • 没读到,去磁盘中读入数据到buffer Pool中
  2. 比对更新前后的数据
    • 如果相同那就不进行更新流程
    • 不同的话那就把更新前的数据和更新后的数据都传给InnoDB层,让InnoDB层执行更新
  3. 开启事务,首先记录相应的undo log,把被更新的列的旧值记录下来,生成undo log语句,写入buffer pool的undo界面,后续的undo log更改都需要记录到redo log buffer里
  4. 开启更新,先更新内存(标记为脏页),再把记录写到redo log buffer里,这个时候更新就完成了。后续会选择一个合适的时机进行脏页刷盘,刷盘时会先刷redo log buffer里的数据再刷脏页的数据。
  5. 一条更新语句执行完后,此时记录的binlog会保存到binlog cache里并没有刷新到硬盘上的binlog文件里,在事务提交时才会将所有的binlog刷新到硬盘。
  6. 事务提交
    • prepare:将redo log状态设为prepare,并将redo log刷新到硬盘里(这个redo log写入磁盘的是数据的变更情况)
    • commit:将binlog刷新到磁盘,接着将redo log状态设置为commit(这个redo log写入磁盘的是事务的状态标记prepare -> commit)
  • undo log:InnoDB存储引擎层的逻辑日志,保证了事务的原子性,用于事务回滚和MVCC
  • redo log:InnoDB存储引擎层的物理日志,保证了事务的持久性,用于掉电等故障的数据恢复
  • bin log:Server层的逻辑日志,用于主从复制和数据备份

逻辑日志和物理日志的区别

  • 逻辑日志:描述的逻辑操作,记录的逻辑语句,恢复的时候需要重放逻辑。结构紧凑。
  • 物理日志:记录的数据的变化例如 对 XXX 表空间中的 YYY 数据页 ZZZ 偏移量的地方做了AAA 更新,占用的空间较大,但是数据恢复的速度快

Redo log

包含两部分一部分是InnoDB存储引擎层的redo log buffer另一部分是磁盘里的redo log file

  • 让事务有了持久性,让MySQL有了崩溃恢复的能力能够保证MySQL在任何时间崩溃,都能够恢复已提交的数据
  • WAL实现了让随机写变成了顺序写(写入redo log是顺序写),提高了IO的效率
    • 具体实现:写操作不立刻写到磁盘上,而是先写到日志上,然后再在合适的时间写到磁盘上
  • undo log页面被修改后要把修改列的旧值写入buffer Pool里的undo页面,同时也要把相关的语句写入redo log里进行持久化存储

undo log

  • 让事务有了原子性
  • 能够实现MVCC

bin log

  • 数据恢复和主从复制

redo log 和 undo log 的使用场景

  • 事务提交之前发生崩溃(不是宕机崩溃而是事务出现问题)重启后会根据undo log回滚事务。
  • 事务提交之后发生崩溃(宕机崩溃)重启后根据redo log恢复事务,不会造成数据丢失。

redo log和bin log的使用场景

  • redo log文件是循环写,边写边擦,只记录未被刷入磁盘的物理地址,已经刷入磁盘的数据会从redo log中擦除。redo log是存储引擎层的日志能够知道脏页刷没刷盘,从而在崩溃恢复的时候恢复那些没被刷盘的脏页数据。
  • binlog 保存的全量的日志,保存了所有数据的变更,只要记录在binlog上的数据都可以恢复,binlog是server层的日志不能知道哪写脏页还没有刷盘。

binlog 两阶段提交过程(为了redo log和binlog的日志一致性,开启了内部XA事务)

  • prepare阶段:将XID写入redo log里,redo log刷入磁盘
  • commit阶段:将XID写入binlog里,binlog刷入磁盘,将redo log状态设置为commit

两个日志出现数据不一致的节点

  • 当MySQL重启的时候会按顺序扫描redo log找到XID后会拿着XID去binlog里去找
    • redo log刷入了磁盘,而还没有将XID写入binlog里。
      • 这个时候redo log里有XID完成了刷盘而binlog里没有XID,发生了数据不一致,进行回滚事务。
    • binlog刷入磁盘,binlog的状态还没设置为commit。
      • 这个时候redo log里有XID完成刷盘并且binlog里也有XID完成刷盘,进行事务提交。
    • 所以对于处于prepare状态的redo log来说既可以进行提交事务也可以进行回滚事务,主要取决于binlog里有没有XID,也就是binlog的写成功为事务成功的标识。
相关推荐
电商api接口开发13 分钟前
ASP.NET MVC 入门指南三
后端·asp.net·mvc
声声codeGrandMaster14 分钟前
django之账号管理功能
数据库·后端·python·django
我的golang之路果然有问题41 分钟前
案例速成GO+redis 个人笔记
经验分享·redis·笔记·后端·学习·golang·go
嘻嘻嘻嘻嘻嘻ys1 小时前
《Vue 3.3响应式革新与TypeScript高效开发实战指南》
前端·后端
暮乘白帝过重山1 小时前
路由逻辑由 Exchange 和 Binding(绑定) 决定” 的含义
开发语言·后端·中间件·路由流程
CHQIUU1 小时前
告别手动映射:在 Spring Boot 3 中优雅集成 MapStruct
spring boot·后端·状态模式
广西千灵通网络科技有限公司1 小时前
基于Django的个性化股票交易管理系统
后端·python·django
CodeFox1 小时前
动态线程池 v1.2.1 版本发布,告警规则重构,bytebuddy 替换 cglib,新增 jmh 基准测试等!
java·后端
tonydf2 小时前
0帧起手本地跑一下BitNet
后端·ai编程
zzmgc42 小时前
常用JVM配置参数
后端