mysql原始碼解讀之事務提交過程 二

2021-09-06 11:52:36 字數 2845 閱讀 4056

測試環境:

os:windows

db:mysql 5.6.12

engine:innodb

配置檔案引數:

log-bin=d:\chuck\mysql\log\5-6-12\mysql-bin

binlog_format=row

set autocommit=0;

sync_binlog=1;

innodb_flush_log_at_trx_commit=1;

innodb_support_xa=1;

測試前置條件:

create table tt(col1 int, col2 varchar(100));

測試語句:

insert into tt values(1, 'abcdef');

commit;

開啟binlog選項後,執行事務提交命令時,就會進入兩階段提交模式。兩階段提交分為prepare階段和commit兩個階段。流程如下 :這裡面涉及到兩個重要的引數:innodb_flush_log_at_trx_commit和sync_binlog,引數可以設定不同的值,具體可以檢視mysql的幫助手冊。我這裡設定的是雙一模式(innodb_flush_log_at_trx_commit=1,sync_binlog=1),不同的模式區別在於,寫檔案呼叫write和落盤fsync呼叫的頻率不同,所導致的後果是mysqld 或 os crash後,不嚴格的設定可能會丟失事務的更新。雙一模式是最嚴格的模式,這種設定情況下,單機在任何情況下不會丟失事務更新。

prepare階段:

1.設定undo state=trx_undo_prepared; //trx_undo_set_state_at_prepare呼叫

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

commit階段:

1.將事務產生的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呼叫

下面這部分是我抽象出來的原始碼呼叫部分,大家可以通過單步除錯方式,在關鍵函式中設定斷點,來詳細了解這個過程。

**********=

prepare階段

**********=

mysql_bin_log::prepare

ha_prepare_low

}**********==

commit階段

**********==

mysql_bin_log::commit

ordered_commit

}  }

mysqld可能在任何情況下crash,os也有可能出現問題,另外若機器掉電,mysqld也會同樣掛掉。但是即使這樣,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

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

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

NHiberante原始碼分析之 事務

對資料庫的操作是少不了事務處理的,事務能保整資料完整性和有效性。在nh中,使用transaction物件對.net的事務物件 實現了idbtransaction介面的物件 進行了包裝。在nh中,乙個典型的事務處理是這樣的 見isession.cs的注釋 isession sess factory.o...

Redis原始碼分析之事務

redis是通過multi discard exec watch四個命令來實現事務的。事務提供了一種將多個命令打包,然後一次性並順序的執行所有命令的機制,並且事務在執行中不會主動中斷,伺服器只有在事務執行完後,才會繼續執行其他客戶端的請求。下面是乙個事務的例子 redis multi okredis...

spring原始碼之事務上篇

本篇之前,已經寫過關於aop的原始碼分析,在此基礎上來閱讀事務的原始碼是比較清晰的。另外,需要對資料庫有一定的了解,我們所說是事務一般指的都是狹義的事務,即資料庫事務。文中沒有特別指出的資料庫,均指的是mysql,後面再來寫一篇關於mysql的鎖和事務的文章。事務指的是乙個程式執行單元,這個執行單元...