binlog
和redo log
区别
为了满足Mysql的事物ACID特性,InnoDB引入了redo log
和 undo log
日志文件。为了满足主从同步Mysql引入了binlog
日志文件。redo log
和binlog
文件都保存的数据库对数据库的修改,但是binlog
和redo log
本质上是不一样的:
redo log
是存储引擎层产生,仅支持Innodb;binlog
是mysql数据上层产生,支持所有存储引擎。redo log
是记录物理日志,记录的是页的物理修改;binlog
记录的是逻辑日志,记录的是SQL语句。redo log
是在事务进过程中产生,日志内容并不是随着事务提交顺序写入;binlog
是在事务提交完成后释放锁之前进行一次性的写入。redo log
主要所用是保证事务持久性;binlog
主要用来所恢复和复制。
为什么需要二阶段提交(2PC)
当redo log
和binlog
数据不一致时就可能导致主从数据不一致,比如:
- 只保存了
redo log
日志,当主节点宕机重启后,主节点可以通过redo log
日志恢复事物,保存数据最新,但是binlog
丢失无法完成主从同步,这样就导致从节点没有最新数据。 - 只保存了
binlog
,当主节点宕机重启后,本机最新事物无法重新执行,数据丢失,但是从库可能通过binlog
已经收到了修改通知,从库将会存在最新数据,而主库没有。
为了避免这种情况,MySQL 引入了两阶段提交的机制。
两阶段提交就是将一个事务分成两个阶段来提交:prepare 阶段和 commit 阶段。在 prepare 阶段,事务会先写 redo log 并将其标记为 prepare 状态,然后写 binlog;在 commit 阶段,事务会将 redo log 标记为 commit 状态,并将 binlog 落盘。这样,无论数据库在哪个时刻发生宕机,都可以根据 redo log 和 binlog 的状态来判断事务是否提交,并保证数据的一致性。
两阶段提交的流程
MySQL采用了如下的二阶段提交流程:
- 在准备阶段,MySQL先将数据修改写入redo log,并将其标记为prepare状态,表示事务还未提交。然后将对应的SQL语句写入bin log。
- 在提交阶段,MySQL将redo log标记为commit状态,表示事务已经提交。然后根据sync_binlog参数的设置,决定是否将bin log刷入磁盘。
通过2PC
机制,MySQL可以保证在任何时刻,redo log和bin log都是逻辑上一致的。如果MySQL发生崩溃,可以根据redo log
恢复数据页的状态,也可以根据bin log
恢复SQL语句的执行。