mysql之事务提交过程(打开binlog)

参考:
http://www.cnblogs.com/cchust/p/3295547.html
http://www.zhdba.com/mysqlops/2012/02/24/mysql-xa-analyze/
http://hedengcheng.com/?p=136

提交流程

打开binlog选项后,执行事务提交命令时,就会进入两阶段(innodb_support_xa参数控制)提交模式。两阶段提交分为prepare阶段和commit两个阶段。
WAL原则必须先刷redo,再刷binlog
prepare阶段:
    1.设置undo state=TRX_UNDO_PREPARED; //trx_undo_set_state_at_prepare调用
    2.刷事务更新产生的redo日志;【步骤1产生的redo日志也会刷入】 innodb_flush_log_at_trx_commit影响刷新策略
    
commit阶段:
   1.将事务产生的binlog写入文件,刷入磁盘;sync_binlog值影响刷新策略
   2.设置undo页的状态,置为TRX_UNDO_TO_FREE或TRX_UNDO_TO_PURGE;  // trx_undo_set_state_at_finish调用
   3.记录事务对应的binlog偏移,写入系统表空间; //trx_sys_update_mysql_binlog_offset调用

异常处理

    mysqld可能在任何情况下crash,os也有可能出现问题,另外若机器掉电,mysqld也会同样挂掉。下面给出几种常见故障场景,
1.prepare阶段,redo log落盘前,mysqld crash
2.prepare阶段,redo log落盘后,binlog落盘前,mysqld crash
3.commit阶段,binlog落盘后,mysqld crash
     
第一种情况,由于redo没有落盘,毫无疑问,事务的更新肯定没有写入磁盘,数据库的一致性受影响;
        回滚
第二种情况,redo log写入完成,但binlog还未写入,事务处于TRX_STATE_PREPARED状态,这是提交还是回滚呢?
        回滚
第三种情况,redo log和binlog都已经落盘,只是undo状态没有更新,这种情况也应该提交,因为redo log和binlog已经一致了。
        提交
     下面给出了mysqld异常重启后的执行逻辑以及关键的源代码。对于第三种情况,我们可以搜集到未提交事务的binlog event,所以需要提交,与我们假设相符;而对于第二种情况,由于binlog未写入,需要通过执行回滚操作来保证数据库的一致性。
 
异常重启后,如何判断事务该提交还是回滚
1.读binlog日志,获取崩溃时没有提交的event;  //info->commit_list中含有该元素,倒叙遍历binlog,直到遇见提交的event?;如果binlog找不到,则会丢失
2.若存在,则对应的事务要提交;   否则需要回滚 
?无法处理情况一
>>> 个人看法
    1、读取redo日志中的prepare状态的event的xid。
        innodb是否可以根据redo中的flush LSN与LSN差别

    2、读取1binlog件的全部数据,将文件中的xid存入commit_list hash表,此list中对应prepare状态的xid
          若binlog文件很大,则效率会变低
        MySQL写Binlog与底层存储引擎(InnoDB)写redo log的方式分析:
        同一事务只能写到同一个Binlog文件中,不能跨文件。
        为了保证底层引擎Commit顺序与Binlog顺序一致,
        目前MySQL+InnoDB不支持group commit(新版Precona,MariaDB除外),同一时间只有一个事务可以进行提交(内部的XA事务,二阶段提交):InnoDB prepare + Binlog flush + InnoDB commit这一系列操作。
        因此下一个事务开始进行InnoDB prepare时,前一个事务的系列动作一定结束,事务已提交。意味着crash recovery时,最多只有一个InnoDB事务处于prepare状态。
        最后一个prepare事务一定位于最后的Binlog文件中
  
    3、commit_list中的xid则根据redo重新提交事务。
        剩余xid,则根据redo回滚事务

简而言之,对于异常的xa事务,若binlog已落盘,则事务应该提交;binlog未落盘,则事务就应该回滚

请使用浏览器的分享功能分享到微信等