先刷redo log盘,然后再删除redo log日志。(redo log刷盘操作是幂等的)
两阶段提交思想
redo log
刷脏页
我们的一条SQL语句,正常执行时速度特别快,但是有的时候不知道为什么,速度特别慢。
那么可能是因为MySQL在刷脏页导致的(flush)
首先先介绍下什么是脏页
- 脏页:内存数据页跟磁盘数据页内容不一致,我们就会称呼这个内存页为脏页
- 干净页:内存数据写入到磁盘后,内存和磁盘上的数据页的内容就一致了。
刷脏页的几种情况
- redo log写满了,此时系统会停止所有更新操作,把checkpoint向前推进,redo log留出空间后才能继续写(redo log是个环形,会涉及到删除原有的内容)
- 需要记录的数据太多,内存页不够,需要淘汰一些数据页,空出内存给别的数据页使用。淘汰的是脏页的话,就要先将脏页写到磁盘中
- MySQL认为系统空闲的时候,会刷脏页
- MySQL正常关闭的时候,会刷脏页
MVCC(MySQL隔离性的保证)
相关概念
视图:InnoDB在实现MVCC时用到的一致性读视图(consistent read view,用于支持RC和RR隔离级别的实现),此处要与查询语句的虚拟表视图(view)区分
多版本和row trx_id
为了保证可重复度,事务在启动时需要对数据库拍一个快照。但是对整个数据库的数据备份一份,无疑是一个很耗性能的工作。那么InnoDB是如何保证可重复度的呢?
基于版本号与undolog
InnoDB每个事务都有一个唯一的事务ID(transaction id),在事务启动时向InnoDB的事务系统申请的,根据申请顺序严格递增的
同时每行数据都是有多个版本的,每次事务更新的时候,都会生成一个新的数据版本,并把transaction id复制给这个数据版本的事务ID,记为 row trx_id。同时也会保存旧的数据版本
U1,U2,U3就是对应的undo log,而V1,V2,V3并不是真是存在的。是根据当前版本和undo log计算出来的
同时,在查询数据的时候,就会以当前事务启动时的版本号为准,对记录进行查找,一直找到当前事务之前的版本号的数据为准
undolog何时删除?在系统中没有比这个回滚日志更早的read-view时,就会删除undolog
**2023/10/10更新**
MySQL运行过程中Crash的该如何恢复
redo log里记录了数据页的修改以及change buffer新写入的信息
如果掉电,持久化的change buffer数据已经purge,不用恢复。主要分析没有持久化的数据
情况又分为以下几种:
(1)change buffer写入,redo log虽然做了fsync但未commit,binlog未fsync到磁盘,这部分数据丢失
(2)change buffer写入,redo log写入但没有commit,binlog以及fsync到磁盘,先从binlog恢复redo log,再从redo log恢复change buffer
(3)change buffer写入,redo log和binlog都已经fsync.那么直接从redo log里恢复。
关于ChangeBuffer对更新时候的帮助
1 | -- a为普通索引,b为普通索引 |
首先先明确下ChangeBuffer的作用
当需要更新一个数据页时,如果数据页在内存中就直接更新,而如果这个数据页还没有在内存中的话,在不影响数据一致性的前提下,InnoDB 会将这些更新操作缓存在 change buffer 中,这样就不需要从磁盘中读入这个数据页了。在下次查询需要访问这个数据页的时候,将数据页读入内存,然后执行 change buffer 中与这个页有关的操作。
由上面的这句话我们可以得出两个结论
- ChangeBuffer适用的场景: 非唯一索引变更
- ChangeBuffer的优点: 减少对索引页的随机读, 提高修改数据的效率
那么我们结合前面的执行流程图和ChangeBuffer,分析下刚刚上面的那个sql, 它在执行的时候分别做了哪些事情?
- 查找索引b, 获取对应的主键id列表
- 回表, 加载对应数据所在的数据页到内存中
- 修改内存中的数据
- 对索引a的修改,记录到change buffer中
- redo log prepare状态
- binlog
- redo log commit状态
- 返回成功
关于binlog是否完整如何判断
- statement 格式的 binlog,最后会有 COMMIT;
- row 格式的 binlog,最后会有一个 XID event。
为什么prepare阶段的redo log加上完整的binlog事务就可以提交
加入binlog写完之后,MySQL发生崩溃,此时binlog已经写入,后面从库包括我们恢复这个奔溃的MySQL都会使用到这个binlog,所以此时奔溃的主库也要提交事务
关于写 redolog
此时MySQL会用到redolog buffer。在插入数据的过程中,生成的日志会先写入到redolog buffer中,等待commit语句执行时redolog buffer才会刷盘
- Post title:Update语句执行流程
- Post author:大黄
- Create time:2021-12-26 13:47:21
- Post link:https://huangbangjing.cn/2021/12/26/Update语句执行流程/
- Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.