【MYSQL】兩階段提交及相關引數介紹
由於Mysql的事務日誌包含二進位制日誌和儲存引擎日誌,當發生崩潰恢復時,MySQL主節點透過redo log進行恢復,而在主從複製的環境下,slaver節點是依據於主節點的binlog進行同步資料的;這樣的架構於是對mysql的二進位制日誌和redo log,就有兩個基本要求:第一,保證binlog裡面存在的事務一定在redo log裡面存在,也就是binlog裡不會比redo log多事務(可以少,因為redo log裡面記錄的事務可能有部分沒有commit,這些事務最終可能會被rollback)。 2、順序一致,這也是很重要的一點,假設兩者記錄的事務順序不一致,那麼會出現類似於主庫事務執行的順序是ta, tb, tc,td,但是binlog裡面記錄的是ta,tc, tb, td,binlog複製到從庫後導致主從的資料不一致。為了達到上面說的兩點,是怎麼來實現的呢?沒錯,答案是內部xa事務(核心是2pc)
一、二階段事務提交流程:
(1)先呼叫binglog_hton和innobase_hton的prepare方法完成第一階段,binlog_hton的papare方法實際上什麼也沒做,innodb的prepare將事務狀態設為TRX_PREPARED,並將redo log刷磁碟
(2)如果事務涉及的所有儲存引擎的prepare都執行成功,則呼叫TC_LOG_BINLOG::log_xid將SQL語句寫到binlog,此時,事務已經鐵定要提交了。否則,呼叫ha_rollback_trans回滾事務,而SQL語句實際上也不會寫到binlog。
(3)最後,呼叫引擎的commit完成事務的提交。實際上binlog_hton->commit什麼也不會做(因為(2)已經將binlog寫入磁碟),innobase_hton->commit則清除undo資訊,刷redo日誌,將事務設為TRX_NOT_STARTED狀態
二、事務恢復流程:
Innodb在恢復的時候,不同狀態的事務,會進行不同的處理(見trx_rollback_or_clean_all_without_sess函式):
<1>對於TRX_COMMITTED_IN_MEMORY的事務,清除回滾段,然後將事務設為TRX_NOT_STARTED;
<2>對於TRX_NOT_STARTED的事務,表示事務已經提交,跳過;
<3>對於TRX_PREPARED的事務,要根據binlog來決定事務的命運,暫時跳過;
<4>對於TRX_ACTIVE的事務,回滾。
簡單來講,當發生崩潰恢復時,資料庫根據redo log進行資料恢復,逐個檢視每條redo的事務狀態,如果根據上圖流程,已進行到TRX_NOT_STARTED階段,也就是儲存引擎commit階段,那麼說明redo log和bin log是一致的,正常根據redo進行恢復即可;事務狀態為TRX_ACTIVE,不用說了,都沒寫到binlog中,直接回滾;但如果事務狀態為TRX_PREPARED,就要分兩種情況了,要先檢查binlog是否已寫入成功?如果沒寫入成功,那麼就算是TRX_PREPARED狀態,也要回滾。如果寫入成功了,那麼就進行最後一步,呼叫儲存引擎commit,更改事務狀態為TRX_NOT_STARTED,也就是真正提交狀態,可以用作資料恢復。
從以上分析可以看出,寫binlog是一定已經提交的資料,只要寫了binlog,事務是鐵定要提交成功的。因為主從複製環境下,寫了binlog就可能直接傳輸到從節點應用了,所以兩階段提交很好的保持資料一致性和順序性
三、相關引數介紹:
1、innodb_support_xa
用於控制innodb是否支援XA事務的2PC,預設是TRUE。如果關閉,則innodb在prepare階段就什麼也不做;這可能會導致binlog的順序與innodb提交的順序不一致(比如A事務比B事務先寫binlog,但是在innodb內部卻可能A事務比B事務後提交),這會導致在恢復或者slave產生不同的資料。
2、sync_binlog
Mysql在提交事務時呼叫MYSQL_LOG::write完成寫binlog,並根據sync_binlog決定是否進行刷盤。預設值是0,即不刷盤,從而把控制權讓給OS。如果設為1,則每次提交事務,就會進行一次刷盤;這對效能有影響(5.6已經支援binlog group),所以很多人將其設定為100。
3、innodb_flush_log_at_trx_commit
innodb_flush_log_at_trx_commit有0、1、2三個值分別代表不同的使redo log落地策略。0表示每秒進行一次flush,但是每次事務commit不進行任何操作(每秒呼叫fsync使資料落地到磁碟,不過這裡需要注意如果底層儲存有cache,比如raid cache,那麼這時也不會真正落地,但是由於一般raid卡都帶有備用電源,所以一般都認為此時資料是安全的)。1代表每次事務提交都會進行flush,這是最安全的模式。2表示每秒flush,每次事務提交時不flush,而是呼叫write將redo log buffer裡面的redo log刷到os page cache。
那現在來比較三種策略的優劣勢:1由於每次事務commit都會是redo log落地所以是最安全的,但是由於fsync的次數增多導致效能下降比較厲害。0表示每秒flush,每次事務提交不進行任何操作,所以mysql crash或者os crash時會丟失一秒的事務。2相對於0來說了多了每次事務commit時會有一次write操作,此時資料雖然沒有落地到磁碟但是隻要沒有 os crash,即使mysql crash,那麼事務是不會丟失的。2相對於0來說會稍微安全一點點。
上面3個引數不同的值會帶來不同的效果。三者都設定為1(TRUE),資料才能真正安全。sync_binlog非1,可能導致binlog丟失(OS掛掉),從而與innodb層面的資料不一致。innodb_flush_log_at_trx_commit非1,可能會導致innodb層面的資料丟失(OS掛掉),從而與binlog不一致
一、二階段事務提交流程:
(1)先呼叫binglog_hton和innobase_hton的prepare方法完成第一階段,binlog_hton的papare方法實際上什麼也沒做,innodb的prepare將事務狀態設為TRX_PREPARED,並將redo log刷磁碟
(2)如果事務涉及的所有儲存引擎的prepare都執行成功,則呼叫TC_LOG_BINLOG::log_xid將SQL語句寫到binlog,此時,事務已經鐵定要提交了。否則,呼叫ha_rollback_trans回滾事務,而SQL語句實際上也不會寫到binlog。
(3)最後,呼叫引擎的commit完成事務的提交。實際上binlog_hton->commit什麼也不會做(因為(2)已經將binlog寫入磁碟),innobase_hton->commit則清除undo資訊,刷redo日誌,將事務設為TRX_NOT_STARTED狀態
二、事務恢復流程:
Innodb在恢復的時候,不同狀態的事務,會進行不同的處理(見trx_rollback_or_clean_all_without_sess函式):
<1>對於TRX_COMMITTED_IN_MEMORY的事務,清除回滾段,然後將事務設為TRX_NOT_STARTED;
<2>對於TRX_NOT_STARTED的事務,表示事務已經提交,跳過;
<3>對於TRX_PREPARED的事務,要根據binlog來決定事務的命運,暫時跳過;
<4>對於TRX_ACTIVE的事務,回滾。
簡單來講,當發生崩潰恢復時,資料庫根據redo log進行資料恢復,逐個檢視每條redo的事務狀態,如果根據上圖流程,已進行到TRX_NOT_STARTED階段,也就是儲存引擎commit階段,那麼說明redo log和bin log是一致的,正常根據redo進行恢復即可;事務狀態為TRX_ACTIVE,不用說了,都沒寫到binlog中,直接回滾;但如果事務狀態為TRX_PREPARED,就要分兩種情況了,要先檢查binlog是否已寫入成功?如果沒寫入成功,那麼就算是TRX_PREPARED狀態,也要回滾。如果寫入成功了,那麼就進行最後一步,呼叫儲存引擎commit,更改事務狀態為TRX_NOT_STARTED,也就是真正提交狀態,可以用作資料恢復。
從以上分析可以看出,寫binlog是一定已經提交的資料,只要寫了binlog,事務是鐵定要提交成功的。因為主從複製環境下,寫了binlog就可能直接傳輸到從節點應用了,所以兩階段提交很好的保持資料一致性和順序性
三、相關引數介紹:
1、innodb_support_xa
用於控制innodb是否支援XA事務的2PC,預設是TRUE。如果關閉,則innodb在prepare階段就什麼也不做;這可能會導致binlog的順序與innodb提交的順序不一致(比如A事務比B事務先寫binlog,但是在innodb內部卻可能A事務比B事務後提交),這會導致在恢復或者slave產生不同的資料。
2、sync_binlog
Mysql在提交事務時呼叫MYSQL_LOG::write完成寫binlog,並根據sync_binlog決定是否進行刷盤。預設值是0,即不刷盤,從而把控制權讓給OS。如果設為1,則每次提交事務,就會進行一次刷盤;這對效能有影響(5.6已經支援binlog group),所以很多人將其設定為100。
3、innodb_flush_log_at_trx_commit
innodb_flush_log_at_trx_commit有0、1、2三個值分別代表不同的使redo log落地策略。0表示每秒進行一次flush,但是每次事務commit不進行任何操作(每秒呼叫fsync使資料落地到磁碟,不過這裡需要注意如果底層儲存有cache,比如raid cache,那麼這時也不會真正落地,但是由於一般raid卡都帶有備用電源,所以一般都認為此時資料是安全的)。1代表每次事務提交都會進行flush,這是最安全的模式。2表示每秒flush,每次事務提交時不flush,而是呼叫write將redo log buffer裡面的redo log刷到os page cache。
那現在來比較三種策略的優劣勢:1由於每次事務commit都會是redo log落地所以是最安全的,但是由於fsync的次數增多導致效能下降比較厲害。0表示每秒flush,每次事務提交不進行任何操作,所以mysql crash或者os crash時會丟失一秒的事務。2相對於0來說了多了每次事務commit時會有一次write操作,此時資料雖然沒有落地到磁碟但是隻要沒有 os crash,即使mysql crash,那麼事務是不會丟失的。2相對於0來說會稍微安全一點點。
上面3個引數不同的值會帶來不同的效果。三者都設定為1(TRUE),資料才能真正安全。sync_binlog非1,可能導致binlog丟失(OS掛掉),從而與innodb層面的資料不一致。innodb_flush_log_at_trx_commit非1,可能會導致innodb層面的資料丟失(OS掛掉),從而與binlog不一致
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29018063/viewspace-2093311/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- [Mysql]兩階段提交MySql
- mysql兩階段提交和組提交MySql
- MySQL事務提交的三個階段介紹MySql
- MySQL中的統計資訊相關引數介紹MySql
- 分散式資料庫事務的兩階段提交介紹分散式資料庫
- MySQL change buffer介紹和相關引數調整建議MySql
- MySQL兩階段提交過程原理簡述MySql
- 淺談mysql的兩階段提交協議MySql協議
- linux的vm相關引數介紹Linux
- MySQL的兩種filesort演算法介紹以及相關引數的設定和優化MySql演算法優化
- 分散式:分散式事務(CAP、兩階段提交、三階段提交)分散式
- vitess兩階段提交事務Vite
- 關於分散式事務、兩階段提交協議、三階提交協議分散式協議
- MySQL效能相關引數MySql
- 全網最牛X的!!! MySQL兩階段提交串講MySql
- 經典的兩階段提交演算法原理及缺陷演算法
- MySQL 連線相關引數MySql
- MySQL slow log相關引數MySql
- mysql innodb相關引數說明MySql
- 分散式基礎,啥是兩階段提交?分散式
- 分散式事務(二)之兩階段提交分散式
- mysql一些引數的介紹MySql
- 08 MySQL兩階段認證MySql
- Linux 核心引數及Oracle相關引數調整LinuxOracle
- 分散式事務的兩階段提交和三階段提交分別有什麼優缺點?分散式
- ArrayList相關方法介紹及原始碼分析原始碼
- MySQL slow log相關引數解釋MySql
- mysql relay log相關引數說明MySql
- 【手摸手玩轉 OceanBase 172】清理備份相關引數介紹
- 關於2PC(二階段提交)和3PC(三階段提交)的理解
- MySQL資料備份多種引數介紹及簡單示例MySql
- Nginx 相關介紹Nginx
- [分享] 使用 golang 理解 MySQL 的兩階段提交- 軒脈刃 de 刀光劍影GolangMySql
- 【分享】使用 golang 理解 mysql 的兩階段提交- 軒脈刃 de 刀光劍影GolangMySql
- (轉)Linux 核心引數及Oracle相關引數調整LinuxOracle
- Mysql 兩階段鎖和死鎖MySql
- 網址url相關引數獲取處理外掛簡單介紹
- Mycat分散式事務兩階段提交過程概述分散式