文章目录
数据库事务的4个特性之一的持久性是数据库保证数据一致性的关键,mysql为了确保事务在系统崩溃后也能恢复,引入了redo log 重做日志这一机制。
什么是redo log
持久性指的是一旦事务提交数据就要永久的保存到数据库中,不能因为数据库的重启而导致数据丢失,其实就是落到磁盘上。如果每次事务的提交都直接写入到磁盘中那么数据肯定就不会丢失了,但是这里有一个问题,数据库数据的落盘是随机读写,这样的话就不知道慢到哪里去了,所以要先把数据保存到缓存池中,过一段时间在刷到磁盘,但是这个时候宕机就可能造成数据丢失,为此又设计了redo log. redolog只记录事务对数据页做了哪些修改,数据页是缓存池中的最小单位,redolog记录的是物理修改,比如说xx空间xx页xx位置xx值。
redo log 组成
redolog分为两个部分,一部分是日志缓存(redo log buffer),一部分是日志文件(redo log file),redolog先写日志缓存,然后特定时机在写入日志文件,一般是三种情况,每秒刷新一次,事务两次提交的时候,log buffer剩余空间小于1/2的时候,日志缓存是循环写的,可以理解为一个环,日志里面还有两个偏移量,一个是写偏移量,一个是已经擦除的位置,就是记录哪些已经更新到数据库了,如何写偏移量追上了擦除偏移量就表示缓存满了,需要落盘写如数据库了。
数据更新流程
- 服务器收到事务开始的指令,为事务生成一个全局唯一的事务ID,redolog和binlog中都会写入这个事务ID。
- 先在缓存页中找到需要更新的数据,如果没有先再磁盘加载缓存,这个时候加载的不是一条记录,是一个缓存页。
- 根据更新指令将缓存页中的数据更新
- 将修改的数据记录到日志缓存中也就是redo log buffer,根据redo log buffer的策略这个时候回不定时的刷新到磁盘
- 服务器收到事务提交的指令,将redo log buffer刷新到磁盘,并将事务改为prepare状态。
- 刷新bin log到磁盘
- 将redo log buffer中的prepare状态改为commit状态,并写入磁盘,事务结束。
两阶段提交
两阶段提交(Two-Phase Commit,简称2PC)是一种在分布式系统中确保事务一致性的协议。它主要用于数据库领域,以保证在分布式系统中的所有节点在进行事务处理时能够保持原子性和一致性。这个协议特别适用于那些需要跨多个节点或服务进行事务处理的场景。Redo log中的两阶段提交 指的是事务提交之后redo log中先改为prepare状态,然后再改为commit状态
binlog
binlog我们一般叫做归档日志,他是mysql服务器层的日志,跟存储引擎无关,他记录的是所有DDL和DML的语句,不包含查询语句,binlog是一种逻辑日志,他记录的是sql语句的原始逻辑,binlog写满后会切换到下一个日志继续写,不会覆盖以前的日志。
binlog有两个重要是使用场景:
- mysq主从复制的时候:主机开启binlog,主机会将binlog同步复制该从节点,从节点通过读取binlog来同步主节点的数据
- mysql的数据恢复:通过使用binlog工具结合binlog可以将数据恢复到数据库某一时刻
binlog 是数据库本身提供的日志,redolog是数据库引擎的日志。
为什么要两阶段提交
为什么要两阶段提交呢?因为两个文件的一致性,bin log 和Redo log。
先看下如果宕机了 数据怎么恢复。如果在prepare阶段还没写入binlog的时候宕机了,恢复的时候先读redolog,发现事务在prepare,再去读binlog,发现binlog没有这个事务,回滚就可以了,如果写完binlog,还没commit的时候宕机了,那就恢复数据就好了,这么问题。
再来看如果没有两阶段提交,那就得先看先写binlog,还是先写redolog,先写binlog,还没有写redolog,数据恢复的时候不一致,如果有从节点的话,从几点会多数据,主节点会丢数据,先写redolog再写binlog,会导致从节点丢数据。
但是不开启binlog的话,那其实就不用考虑二次提交了,直接写redolog置为commit也不会有问题,因为不需要考虑两个文件的一致性了,为了提高读写效率加了redolog,为了binlog和redolo的一致性事务完成性,又加了二次提交
结语
后来我在想如果没有redolog,直接用binlog可不可以,既然官方这么设计了,那肯定是有理由的。我想binlog记录的不是具体的物理数据,记录的事DDL和DML语句,如果数据恢复的话可能就会出问题了,比如说我放缓存的数据丢失了,那么应该从哪里恢复呢?根本没法记录,更别提恢复数据了。而且Mysql最开始是没有InnoDb引擎的,自带的引擎是MyLSam,Mylsam不支持事务,也没有崩溃恢复的能力,后来才有了InnoDb支持事务,所以才有了引擎层的日志Redolog,具体对不对就不知道了,用就好了