MySQL事務提交過程(二)

上一篇文章咱們介紹了在關閉binlog的狀況下,事務提交的大概流程。之因此關閉binlog,是由於開啓binlog後事務提交流程會變成兩階段提交,這裏的兩階段提交併不涉及分佈式事務,固然mysql把它稱之爲內部xa事務(Distributed Transactions),與之對應的還有一個外部xa事務。 html

這裏所謂的兩階段提交分別是prepare階段和commit階段。 mysql

內部xa事務主要是mysql內部爲了保證binlog與redo log之間數據的一致性而存在的,這也是由其架構決定的(binlog在mysql層,而redo log 在存儲引擎層);sql

外部xa事務則是指支持多實例分佈式事務,這個纔算是真正的分佈式事務。 數據庫

既然是xa事務,必然涉及到兩階段提交,對於內部xa而言,一樣存在着提交的兩個階段。服務器

下文會結合源碼詳細解讀內部xa的兩階段提交過程,以及各類狀況下,mysqld crash後,mysql如何恢復來保證事務的一致性。 網絡

   

測試環境 架構

OS:WIN7分佈式

ENGINE:性能

DB:測試

   

配置文件參數:

log-bin=D:\mysql\log\5-6-21\mysql-bin

binlog_format=ROW

set autocommit=0;

innodb_support_xa=1

sync_binlog=1;

innodb_flush_log_at_trx_commit=1;

【innodb_flush_log_at_trx_commit=1,sync_binlog=1

不一樣的模式區別在於,寫文件調用write和落盤fsync調用的頻率不一樣,所致使的後果是mysqld 或 os crash後,不嚴格的設置可能會丟失事務的更新。

雙一模式是最嚴格的模式,這種設置狀況下,單機在任何狀況下不會丟失事務更新。】

   

測試條件

set autocommit=0;
-- ----------------------------

-- Table structure for `user`

-- ----------------------------

DROP TABLE IF EXISTS `user`;

CREATE TABLE `user` (

`id` int(20) NOT NULL,

`account` varchar(20) NOT NULL,

`name` varchar(20) NOT NULL,

PRIMARY KEY (`id`),

KEY `id` (`id`) USING BTREE,

KEY `name` (`name`) USING BTREE

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

   

測試語句

insert into user values(1, 'sanzhang', '張三');
commit;

   

prepare階段:

    1.設置undo state=TRX_UNDO_PREPARED //trx_undo_set_state_at_prepare調用

    2.刷事務更新產生的redo日誌;【步驟1產生的redo日誌也會刷入】

MYSQL_BIN_LOG::prepare

ha_prepare_low

    {

engine:

binlog_prepare

innobase_xa_prepare

mysql:

trx_prepare_for_mysql

{

                1.trx_undo_set_state_at_prepare    //設置undo段的標記爲TRX_UNDO_PREPARED

                2.設置事務狀態爲TRX_STATE_PREPARED

                3.trx_flush_log_if_needed  //將產生的redolog刷入磁盤

            }

     }

     

commit階段:

   1.將事務產生的binlog寫入文件,刷入磁盤;

   2.設置undo頁的狀態,置爲TRX_UNDO_TO_FREETRX_UNDO_TO_PURGE;  // trx_undo_set_state_at_finish調用

   3.記錄事務對應的binlog偏移,寫入系統表空間; //trx_sys_update_mysql_binlog_offset調用

MYSQL_BIN_LOG::commit

    ordered_commit

   {

1.FLUSH_STAGE

        flush_cache_to_file  //  刷binlog

2.SYNC_STAGE

        sync_binlog_file    //Call fsync() to sync the file to disk.

3.COMMIT_STAGE

        ha_commit_low

        {

            binlog_commit

            innobase_commit   

                trx_commit(trx) 

                {

                    trx_write_serialisation_history(trx, mtr);  //更新binlog位點,設置undo狀態

                    trx_commit_in_memory(trx, lsn); //釋放鎖資源,清理保存點列表,清理回滾段

                }        

        } 

    }

   

在任何狀況下(機器掉電)mysqld crash或者os crash,MySQL仍然能保證數據庫的一致性。數據的一致性是如何作到的哪?正是二階段提交。

咱們結合幾種場景來分析下二階段提交是如何作到的:

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中含有該元素

2.若存在,則對應的事務要提交;不然須要回滾。

   

判斷事務提交或回滾源碼以下:

   

上面討論了兩階段提交的基本流程,以及服務器異常crash後,mysql如何重啓恢復保證binlog和數據的一致性。

簡而言之,對於異常的xa事務,若binlog已落盤,則事務應該提交;binlog未落盤,則事務就應該回滾。

   

//異常重啓後,回滾流程

innobase_rollback_by_xid

rollback_by_xid

trx_rollback_resurrected

    trx_rollback_active

        row_undo

        {

            //從回滾頁獲取undo記錄

            //分析undo記錄類型

            if (insert)

                row_undo_ins

            else

                row_undo_mod

        }

 

   

//異常重啓後,提交流程

commit_by_xid

trx_commit_for_mysql

   

//寫binlog接口

handler.cc:binlog_log_row

sql/binlog.cc:commit

mysys/my_sync:my_sync

sql/binlog.cc:sync_binlog_file

handler/ha_innodb.cc:innobase_xa_prepare

   

binlog日誌文件是爲了解決MySQL主從複製功能而引入的一份新日誌文件,它包含了引起數據變動的事件日誌集合。

從庫請求主庫發送 binlog 並經過日誌事件還原數據寫入從庫,因此從庫的數據來源爲 binlog。

這樣 MySQL 主庫只需作到 binlog 與本地數據一致就能夠保證主從庫數據一致(暫且忽略網絡傳輸引起的主從不一致)。

   

參考

   一、《高性能MySQL》

   二、mysql 事務提交過程

相關文章
相關標籤/搜索