对于解决MySQL中binlog和InnoDB的redolog日志同步的问题,MySQL采用了内部XA(两阶段提交)
MySQL的内部XA
流程
- prepare阶段:
第一阶段,事物管理器向所有涉及到的数据库服务器发出prepare“准备提交”请求,数据库收到请求后执行数据修改和日志纪律等处理,处理完成后只是把事务状态改成可以提交 ,然后把结果返回给事务管理器 - commit阶段:
事物管理器收到回应后进入第二阶段,如果在第一阶段内有任何一个数据库的操作发生错误,或者事物管理器收不到某个额数据库的回应, 则认为事务失败,回撤所有数据库的事物。 数据库服务器收不到第二阶段的确认提交 请求,也会把可以提交的事物回撤。 如果第一阶段中所有数据库都提交成功,那么事物管理器向数据库服务器发出确认提交请求,数据库服务器吧事务的可以提交 状态修改为提交完成 状态,然后返回应答 也就是说redolog更新后等待binlog更新完再commit
崩溃恢复过程
- 如果数据库在记录此事务的binlog之前和过程中发生crash。数据库在恢复后认为此事务并没有成功提交,则会回滚此事务的操作。与此同时,因为在binlog中也没有此事务的记录,所以从库也不会有此事务的数据修改。
- 如果数据库在记录此事务的binlog之后发生crash。此时,即使是redo log中还没有记录此事务的commit 标签,数据库在恢复后也会认为此事务提交成功(因为在上述两阶段过程中,binlog写入成功就认为事务成功提交了)。它会扫描最后一个binlog文件,并提取其中的事务ID(xid),InnoDB会将那些状态为Prepare的事务(redo log没有记录commit 标签)的xid和Binlog中提取的xid做比较,如果在Binlog中存在,则提交该事务,否则回滚该事务。这也就是说,binlog中记录的事务,在恢复时都会被认为是已提交事务,会在redo log中重新写入commit标志,并完成此事务的重做(主库中有此事务的数据修改)。与此同时,因为在binlog中已经有了此事务的记录,所有从库也会有此事务的数据修改。
参考文章 MySQL中binlog和redo log的一致性问题 mysql 提交事务_MySQL事务提交过程
|