MySQL是一个关系型数据库管理系统,它使用SQL(Structured Query Language)作为主要的数据操作语言。在MySQL中,特别是在InnoDB存储引擎中,数据修改过程涉及到两种重要的日志:redo log(重做日志)和undo log(回滚日志)。
1 redo log(重做日志)
Redo log用于保证事务的持久性。当你修改数据时,这些修改首先会被写入到redo log中,并且几乎是同时写入到内存中的数据页。如果数据库系统发生崩溃,那些还没有被持久化到磁盘上的内存页修改可以通过重播redo log来恢复。Redo log采用的是循环写入的方式,它分为两个部分:一部分在内存中,称为log buffer,另一部分在磁盘上。
修改数据的步骤通常包括:
- 将修改操作写入到redo log buffer。
- 修改内存中的数据页。
- 在适当的时候,将redo log buffer中的内容刷新(flush)到磁盘上。
2 undo log(回滚日志)
Undo log用于多个目的,包括回滚事务中未提交的操作,以及提供MVCC(多版本并发控制)时所需的旧版本数据。当对数据进行修改时,会在undo log中记录一个逆向操作。如果一个事务需要回滚,或者其他事务需要看到修改前的数据,undo log将被用来恢复或者提供数据的旧版本。
修改数据时,undo log的流程通常如下:
- 记录数据修改前的状态到undo log。
- 执行数据修改。
- 如果事务提交,则最终会清除掉相应的undo log记录。如果发生回滚,则使用undo log来撤销已经执行的修改。
3 Binlog(二进制日志)
Binlog是MySQL中的二进制日志,用于记录数据库的逻辑改变,如对数据库中的数据进行了怎样的操作(增删改)。通过Binlog,可以对数据库进行基于时间点的恢复、数据复制和主从同步。Binlog的存在为数据备份、恢复和同步提供了强大的支持。
4 两阶段提交
两阶段提交发生在redo log和bin log日志写入阶段,把日志写入和日志提交分为两个阶段(prepare准备、commit提交)
4.1 执行过程
- 当执行一条update语句的时候,首先会记录到buffer pool里面,然后对应在undo log中更新历史数据,在redo log中更新修改数据并修改状态为prepare。
- 当事务commit的时候会向bin log里面写入修改逻辑,同时修改undo log状态为commit。
之后修改过后的数据是异步写入磁盘的。
4.2 系统崩溃后重启如何刷新数据
- 当写入undo log之前崩溃,这时undo log和bin log中都没有数据,此时满足数据一致性不需要进行操作。
- 当在写入bin log之前崩溃,此时根据undo log中的事务id去bin log中查找是没有数据的,因此会回滚。
- 当在写入bin log之后崩溃,无论undo log有没有修改为commit状态,都会把数据更新到磁盘。
4.3 redo log 和 bin log区别
- redo log是innodb存储引擎独有的,binlog是不区分存储引擎
- 记录内容不同, redo log是物理日志,记录事务具体操作的内容; bin log是逻辑日志,记录事务操作过程
- 写入时间不同,先写入redo log,再写入binlog
- redo log是循环使用文件,bin log每次新增一个文件