MySQL的redo log 、undo log、 binlog
redo log概念
redo log翻译过来叫重做日志,是一种保证持久化的措施,innodb存储引擎的物理日志文件
redo log是固定大小的,是循环写的过程
有了redo log之后,innodb就可以保证即使数据库发生异常重启, 之前的记录也不会丢失,叫做crash-safe
undo log概念
Undo Log是为了实现事务的原子性,在MySQL数据库InnoDB存储引擎中, 还用Undo Log来实现多版本并发控制(简称:MVCC)
操作任何数据之前,首先将数据备份到一个地方(这个存储数据备份的地方 称为Undo Log)。然后进行数据的修改。如果出现了错误或者用户执行了 ROLLBACK语句,系统可以利用Undo Log中的备份将数据恢复到事务开始之 前的状态
注意:undo log是逻辑日志,undo log记录在redo log里面,可以理解为:
- 当delete一条记录时,undo log中会记录一条对应的insert记录
- 当insert一条记录时,undo log中会记录一条对应的delete记录
- 当update一条记录时,它记录一条对应相反的update记录
binlog概念
bin log是服务端的日志文件,主要做mysql功能层面的事情
与redo日志的区别:
1、redo是innodb独有的,binlog是所有引擎都可以使用的
2、redo是物理日志,记录的是在某个数据页上做了什么修改,binlog是逻 辑日志,记录的是这个语句的原始逻辑
3、redo是循环写的,空间会用完,binlog是可以追加写的,不会覆盖之前 的日志信息
数据刷盘流程
innodb是用页单位来管理存储空间的,任何的DML都会操作完整的一个页,会将整个页加载到用户态中内存下的Buffer Pool中,然后对需要修改的数据进行修改,这时数据不会立即刷新到到磁盘(目的是不浪费磁盘IO)而是通过undo log 数据备份、redo log先记录数据变化,再由异步线程把数据刷到磁盘上,这样即使系统崩溃,再恢复后,也可以根据redo日志进行数据恢复。
- 当发生数据修改的时候,innodb引擎会先将记录写到redo log中, 并更新内存,此时更新就算是完成了,同时innodb引擎会在合适 的时机将记录操作到磁盘中
- redo log 是以组的方式写入,在一个事务中,这些redo log称为一个组redo log, 组redo log具有原子性
- Log Buffer 16MB 每个Buffer由Block组成,每个Block块 512byte
redo log刷盘时机
通过参数innodb_flush_log_at_trx_commit控制
- commit的时候进行刷盘:这也是最保险的,因为如果这个时候崩溃了代表没有commit成功,因此,也不用恢复什么数据
- commit的时候,只是刷新近os的内核缓冲区,具体的刷盘时机不确定
- 后台线程,每s刷新一次到磁盘中
两阶段提交
通过redo log、和bin log来保证数据一致性,不同阶段断电情况如下
更改数据:redo log 和bin log都没有持久化,因此数据是一致的
写redo log(prepare状态):mysql重启后,首先检查redo log状态,如果有并且状态处于prepare状态,查看有没有bin log日志,有的话正常提交,没有则删除处于prepare的redo log
写binlog:mysql重启后,查看有没有bin log日志,有的话正常提交,没有则删除处于prepare的redo log
提交事务commit状态:此时走刷盘机制
事务commit成功
事务执行commit命令后,mysqld将记录了数据修改的Log Buffer写入磁盘上的redo log,然后将这部分数据的状态修改为commit,写完redo log后才算是事务提交成功,MySQL Server需要保持commit状态的数据的持久性。如果写redo log失败,数据的状态还是prepare,尽管事务执行了commit命令,这依然不算commit成功
DML完整的执行步骤
update table set column = x where id = 1;
- 获取数据库连接
- 判断id=1的这条记录在不在buffer pool中,在的话undo log备份,执行更新,否则从磁盘中加载到buffer pool中,然后进行undo log备份、更新
- 将这个更新操作记录到redo log中,记录的是一个物理日志。此时redo log是一个prepare状态
- 记录该操作的binlog,并且将binlog刷盘
- 提交事务,对redo log进行提交。
时redo log是一个prepare状态
4. 记录该操作的binlog,并且将binlog刷盘
5. 提交事务,对redo log进行提交。