Mysql杂志(三十二)——redo日志、undo日志
我们在说这个的时候先来回顾一下什么是ACID,分别是原子性、一致性、隔离性、持久性。
特性 | 英文全称 | 核心目标 | MySQL实现机制 |
---|---|---|---|
A | Atomicity(原子性) | 事务要么全部完成,要么全部不执行 | undo log + 事务状态管理 |
C | Consistency(一致性) | 数据库从一个一致状态转换到另一个一致状态 | 约束+触发器+业务逻辑 |
I | Isolation(隔离性) | 并发事务相互隔离 | MVCC + 锁机制 |
D | Durability(持久性) | 提交的事务永久保存 | redo log + 双写缓冲 |
Redo日志
edo log(重做日志)是 InnoDB 引擎特有的物理日志,记录的是数据页的物理修改,而非逻辑操作。它是 MySQL 实现 WAL(Write-Ahead Logging)预写式日志的核心组件。
我们之前在mysql的逻辑结构的时候说过,没有sql的增删改查是先在内存中修改的,所以大家觉得很快,好像感觉不到索引带来的增删改的负面影响,而这个Redo日志就是保障我们我们数据的持久性的。
首先我们增删改查一个操作,第一步是通过索引把磁盘内容加载到内存中,
第二步是修改内存的值同时把修改后的值放入redo log buffer中,这个redo log buffer大小默认是16M(索引数据页的大小是16K),这个可以通过
show variables like '%innodb_log_buffer_size%'
这个命令查看,也可以通过这个命令进行修改,
SET GLOBAL innodb_log_buffer_size = 67108864; -- 设置为64MB
我们的服务器启动的时候会给redolog分配若干个缓存块,一个块是512k,总共大小就是innodb_log_buffer_size。
第三步,当这个操作提交了,会把redolog buffer中的数据写入redolog file中。
第四步,就是等到系统刷盘了。
好了大家应该对数据的修改有了一个很清晰的认识了,但是我们还是要说一下redolog buffer刷入到redofile中的三种行为,因为这也是一个刷盘的行为,我们可以通过查询系统变量来查看我们的innodb_flush_log_at_trx-commit这个是什么值,使用show variables查看,如果是1(默认)那就是每当事务提交后就立刻刷入redolog file中,如果是0,那么就是由mysql的后台进程每间隔一秒刷入redolog file中,如果是2那就是把提交的buffer内容提交到page cache中由我们的OS操作系统来决定什么时候刷盘。
Undo日志
undolog是所有DML操作的副本快照,DML操作之前都会有一个前置操作,就是把未修改前的数据写入到undolog中,当事务回滚就会恢复原来的数据,达到原子性的要求。因为undolog也是操作了数据库所以会生成对应的redolog以达到持久性需求。
然后就是undolog是逻辑的,不是物理的,但是这个逻辑并不是说没有存,而是存在了内存中一个叫做回滚段中,不记得段的小伙伴看一下https://blog.csdn.net/qq_45041250/article/details/152030060?spm=1001.2014.3001.5502
现在innoDB默认是128个区(但其实叫回滚段(Rollback Segment)),一个区就是1m同时包含1024 个 undo slot,每个slot就是一个事务。所以说的回滚段其实是一个区,因为区才是物理结构,段是逻辑结构,只是大家习惯这么叫了而已,所以mysql现在最大同时支持128*1024个事务在线,当然这个区的大小是可以设置的不止128,但是这个要更加内存去,不是越大越好的。
然后undolog存的数据有三种类型,一种是事务未提交的数据,一种是事务已经提交但是数据未过期的数据,还有一种是事务已经提交但是过期的数据。
这些未过期或者未清理的数据指的都是尚未被purge线程清理的undo记录,这些数据仍可能被以下场景使用:正在运行的读视图需要访问旧版本、闪回查询需要历史数据、延迟的二级索引清理,下面这个就是配置。undolog有专门的线程清理记录,而redolog file是循环覆盖的,原理和监控的原理一样。
参数 | 默认值 | 作用 | 推荐值 |
---|---|---|---|
| 0 | 触发延迟清理阈值 | 1000-5000 |
| 300 | 每次清理数量 | 500-1000 |
| 4 | 清理线程数 | 8-16(高并发) |
然后undolog中的数据有2种类型,一种是inser产生的数据,事务提交数据就会过期然后直接被删除,还有一种就是删除和修改操作,这个就需要经历上面的三种情况,因为可能其他事务要读取事务未提交之前的数据,所以不能随便删除。
还记得我们之前将索引和行格式的时候,回滚指针(DB_ROLL_PTR)和事务ID(DB_TRX_ID) 这俩家伙吗,现在应该很好理解这俩哥们的作用是啥了吧。然后undolog是一个链表,永远指向前一个版本的undolog。
总结
好了现在应该对Mysql如何保存强一致性应该就有一定的了解了吧,如果事务中途发生错误会使用undolog回滚复原,如果服务器突然崩溃也可以通过redolog进行恢复,就是redolog刷盘完成了一半,也可以通过事务id去检查数据是否全部刷盘成功,如果没有继续把没成功的数据刷盘,这一套流程保证了Mysql的数据强一致性。