91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

MySQL中并行復制亂序提交引起的同步異常如何處理

發布時間:2021-11-06 09:14:43 來源:億速云 閱讀:147 作者:小新 欄目:MySQL數據庫

這篇文章將為大家詳細講解有關MySQL中并行復制亂序提交引起的同步異常如何處理,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

現象描述

Slave在開啟并行復制后, 默認會亂序提交事務, 可能會引起同步中斷;

Slave端表現為同步的SQL線程拋出異常, 為主鍵重復, 修改的數據行不存在等;

GTID信息類似于: 9a2a50aa-5504-11e7-9e59-246e965d93f4:1-1371939844:1371939846

其中1371939845為報錯的事務, 直觀上看, Slave端先提交了1371939846事務;


解決辦法

MySQLversion>=5.7.5
slave_preserve_commit_order:OFF(default)->ON
注:binlog_order_commits=ON(default)


問題分析

參考官方的WL#6314和WL#7165, 這里對原文內容進行簡單的歸納, 有興趣的可以看看原文的High Level Architecture;
WL#6314 : https://dev.mysql.com/worklog/task/?id=6314
WL#7165 : https://dev.mysql.com/worklog/task/?id=7165
注: 英文原文中的commit-parent transaction, sequence number指的就是binlog中的last_commited和sequence_number; 即簡單翻譯中的”邏輯時間戳標記” 

WL#6314 關于slave端的并行applier

當事務進入prepare階段(組提交流程的某一個階段)時, 這些事務都會獲得一個邏輯時間戳的標記, 用來標記最新提交的事務是哪個;

在master端, 有關流程如下:

  • 在prepare階段, 從commit_clock中獲取時間戳并存儲下來, 用來標記最新提交的事務;

  • 在commit階段(事務已經寫入binlog, 但是在引擎層提交前), 對commit_clock執行步進操作;

在Slave端, 有關流程如下:

  • coordinate線程會讀取relaylog的event, 如果這些event都有相同的邏輯時間戳(last_commited), 那么這些event就可以由worker并行執行;

WL#7165 有關并行復制的并行度優化

參照WL#6314的描述, 雖然已經實現了并行復制, 但是并沒有達到預期的程度;

舉例: 下圖代表各個事務的執行順序與時間線, 其中P代表單個事務的prepare階段, 在這個階段會獲取到commit_clock的時間戳, C代表這個事務的寫binlog的階段, 在這里會對commit_clock進行步進操作;

MySQL中并行復制亂序提交引起的同步異常如何處理

如上圖所示, Trx1, Trx2, Trx3的P階段獲取到的都是同一個last_commited值(比如說是1), 因此這三個事務可以在Slave端并行執行; 同理, Trx4不能和< Trx1, Trx2, Trx3 > 一起并行回放, 因為Trx4的P階段, 獲取到的last_commited值是Trx1執行完步進以后的值(步進之后變成了2); 

按照WL#6314的邏輯, Slave端可以發現這七個事務分成了四個事務組, 分別是< Trx1, Trx2, Trx3 >, < Trx4 >, < Trx5, Trx6 >, < Trx7 >;

但是需要注意的是, 對于不同的事務組, < Trx4 > 和 < Trx5, Trx6 > 是能并發執行的, 因為從時間線上看, < Trx4 > 和 < Trx5, Trx6 > 的prepare階段在時間線上是有重疊的, 這也就意味著這兩組事務并不存在鎖的沖突, 那么就可以在Slave并行執行;

對于并行度的優化

改進后的并行復制使用鎖來判斷是否可以進行并發;

基本邏輯如下:

L代表鎖階段開始, C代表鎖階段結束;

MySQL中并行復制亂序提交引起的同步異常如何處理

A中的Trx1和Trx2由于鎖階段存在重合, 也沒有發生沖突, 說明Trx1和Trx2是可以并行執行的, 但是B不行, 因為Trx1和Trx2的鎖階段沒有重合, 所以無法確認是不是可以并行執行(不做額外的判斷, 直接當做不可并行處理, 節約性能開銷);

關于鎖階段的判斷, WL中明確表示沒有進行鎖分析, 而是直接把事務提交的一些階段作為加鎖與釋放鎖的時間點(從事務提交的階段來看, 也沒什么問題);

  • 假設在進行存儲引擎層的提交之前, 所有的鎖都已已經釋放(鎖階段結束的時間點);

  • 假設在prepare階段開始的時候, 所有需要的鎖已經全部獲取到(鎖階段開始的時間點);


在MySQL的binlog中, L所指的標記就是last_commited, C所指的標記就是sequence_number;

關于last_commited和sequence_number, WL#7165有做如下描述

  • 在事務進入flush階段前, 會步進transaction.sequence_number的值 –> 顯示為sequence_number

  • 在事務進入引擎層提交之前, 會修改 global.max_committed_transaction的值 

    • = max(global.max_committed_timestamp, transaction.sequence_number) 

    • = transaction.sequence_number (如果binlog_order_commits使用默認值ON)


因此, Slave端在決定SQL是否可以并發執行時, 參考如下原則:

-----------------------------------------------------------------------------------------------------------
Slave can execute a transactionifthe smallest sequence_number 
    among all executing transactions is greater than transaction.last_committed.
-----------------------------------------------------------------------------------------------------------

偽代碼會更直觀一些:
-----------------------------------------------------------------------------------------------------------
Slave logic:
    -before scheduler pushes the transaction for execution : wait until         transaction_sequence[0].sequence_number>transaction.last_committed
-----------------------------------------------------------------------------------------------------------

所以使用基于鎖的并行度優化后, 確實可以讓WL#6314的< Trx4 > 和 < Trx5, Trx6 > 并發執行;

故障場景還原

Slave上報錯的事務為1371939845, binlog內容如下, 事務缺少1371939845; 
MySQL中并行復制亂序提交引起的同步異常如何處理
Master上的事務序列如下: 
MySQL中并行復制亂序提交引起的同步異常如何處理

參考WL#6314的格式, 根據Master的事務序列繪制事務序列圖, GTID, last_commited, sequence_number均使用最后兩位數作為標記;

由于Slave是亂序提交的, 所以這些事務在Slave的binlog中并非嚴格按照GTID遞增的順序出現

MySQL中并行復制亂序提交引起的同步異常如何處理

根據WL#7165的描述, 可以得出: 在Slave上, 當Trx41執行完畢之后, Slave認為, Trx46與Trx47已經可以由coordinate進行調度, 與< Trx42, Trx43, Trx44, Trx45 > 并行執行了, 但是Trx45與Trx46, Trx47 存在業務上的先后順序(且確實存在鎖沖突), 所以先執行的Trx46刪除了Trx45需要的數據, 導致同步中斷;

PS: 既然Trx45和Trx46有鎖沖突, 為什么Trx46會拿到84作為last_commited, 而不是88?


參考WL#7165的偽代碼,
-----------------------------------------------------------------------------------------------------------
When@@global.binlog_order_commitsistrue,inprinciple we could reduce  the max
    to an assignment:
     global.max_committed_transaction=transaction.sequence_number
-----------------------------------------------------------------------------------------------------------
MySQL-5.7.21的源代碼:
MYSQL_BIN_LOG::ordered_commit-->
process_commit_stage_queue-->
update_max_committed
-----------------------------------------------------------------------------------------------------------

因此推測主庫當時候是如下場景:<Trx35~Trx45>作為一個事務組,進入到了存儲引擎的commit階段前,會遞增sequence_number,而不是一次到位的全部加上;

所以Trx46進入prepare階段時,剛好是Trx41完成了commit階段,所以拿到的是84,而不是88;雖然官方描述中,認為會達到最終一致的狀態,但是同步過程中會存在短暫的不一致現象,這種現象被描述為"GAP";

關于“MySQL中并行復制亂序提交引起的同步異常如何處理”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

通榆县| 清丰县| 民乐县| 普洱| 通化市| 延寿县| 上虞市| 望江县| 庆安县| 永福县| 怀来县| 东明县| 道真| 沧州市| 富锦市| 东阿县| 麻江县| 黔南| 山阴县| 绥芬河市| 桦川县| 长丰县| 瑞金市| 卢湾区| 涿州市| 哈尔滨市| 彭泽县| 丰城市| 闸北区| 宜昌市| 吴桥县| 镶黄旗| 常德市| 武安市| 靖西县| 株洲市| 山西省| 抚州市| 吴江市| 南涧| 清原|