学习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的写成功为事务成功的标识。
相关推荐
江梦寻1 小时前
MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
开发语言·后端·python·macos·架构·策略模式
风象南1 小时前
SpringBoot的4种死信队列处理方式
java·spring boot·后端
互联网全栈架构2 小时前
遨游Spring AI:第一盘菜Hello World
java·人工智能·后端·spring
coderSong25687 小时前
Java高级 |【实验八】springboot 使用Websocket
java·spring boot·后端·websocket
Mr_Air_Boy8 小时前
SpringBoot使用dynamic配置多数据源时使用@Transactional事务在非primary的数据源上遇到的问题
java·spring boot·后端
咖啡啡不加糖9 小时前
Redis大key产生、排查与优化实践
java·数据库·redis·后端·缓存
大鸡腿同学10 小时前
纳瓦尔宝典
后端
2302_8097983211 小时前
【JavaWeb】Docker项目部署
java·运维·后端·青少年编程·docker·容器
zhojiew12 小时前
关于akka官方quickstart示例程序(scala)的记录
后端·scala