[MySQLソース]:トランザクションコミットのInnoDB Prepare

2876 ワード

MySQL 5.6 InnoDB Prepareの流れは以下の通りです.
innobase_xa_prepare  // InnoDB Prepare 
    trx_prepare_for_mysql   //   Prepare
        {
        trx->op_info = "preparing"; //          preparing
        trx_prepare(trx);  ////  Prepare
            trx_undo_set_state_at_prepare()  //  undo   Prepare
                undo->state = TRX_UNDO_PREPARED;
                undo->xid   = trx->xid;
            trx->state = TRX_STATE_PREPARED  //      
            trx_flush_log_if_needed(lsn, trx);  //  redo  
                {
                trx->op_info = "flushing log";
                trx_flush_log_if_needed_low(lsn); //     lsn redo
                    log_write_up_to()    //    redo   
                trx->op_info = "";
                }
        trx->op_info = "";  //          ""
        }

innodb_flush_log_at_trx_commitパラメータは、trx_flush_log_if_needed_low関数では0:redoをリフレッシュしないことを示し、何もしない1:redoをリフレッシュし、ログをディスクにリフレッシュする2:redoをリフレッシュするが、落盤はオペレーティングシステムによって制御される
trx_flush_log_if_needed_low(
/*========================*/
    lsn_t    lsn)    /*!< in: lsn up to which logs are to be
            flushed. */
{
    switch (srv_flush_log_at_trx_commit) {
    case 0:      //     0       
        /* Do nothing */
        break;
    case 1:      //   1 ,flush redo     
        /* Write the log and optionally flush it to disk */
        log_write_up_to(lsn, LOG_WAIT_ONE_GROUP,
                srv_unix_file_flush_method != SRV_UNIX_NOSYNC);
        break;
    case 2:      //   2 ,flush redo,       
        /* Write the log but do not flush it to disk */
        log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, FALSE);

        break;
    default:
        ut_error;
    }
}      

5.6 InnoDB Prepareに比べて5.7が最適化され、Innodb Prepareフェーズではflushログは再利用されず、flush redoをbinlog flushフェーズに調整してredologのグループコミットを実現
if (prepare_trx
	    || (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {

		/* We were instructed to prepare the whole transaction, or
		this is an SQL statement end and autocommit is on */

		ut_ad(trx_is_registered_for_2pc(trx));

		dberr_t	err = trx_prepare_for_mysql(trx);

		ut_ad(err == DB_SUCCESS || err == DB_FORCED_ABORT);

		if (err == DB_FORCED_ABORT) {

			innobase_rollback(hton, thd, prepare_trx);

			return(convert_error_code_to_mysql(
				DB_FORCED_ABORT, 0, thd));
		}

	} else {
		/* We just mark the SQL statement ended and do not do a
		transaction prepare */

		/* If we had reserved the auto-inc lock for some
		table in this SQL statement we release it now */

		lock_unlock_table_autoinc(trx);

		/* Store the current undo_no of the transaction so that we
		know where to roll back if we have to roll back the next
		SQL statement */

		trx_mark_sql_stat_end(trx);
	}

[MySQLソース]:2 PCでのトランザクションコミットの概要