1. 程式人生 > 資料庫 >深入淺出講解MySQL的並行複製

深入淺出講解MySQL的並行複製

一、並行複製的背景

首先,為什麼會有並行複製這個概念呢?

1. DBA都應該知道,MySQL的複製是基於binlog的。

2. MySQL複製包括兩部分,IO執行緒 和 SQL執行緒。

3. IO執行緒主要是用於拉取接收Master傳遞過來的binlog,並將其寫入到relay log

4. SQL執行緒主要負責解析relay log,並應用到slave中

5. 不管怎麼說,IO和SQL執行緒都是單執行緒的,然後master卻是多執行緒的,所以難免會有延遲,為了解決這個問題,多執行緒應運而生了。

6. IO多執行緒?

6.1 IO沒必要多執行緒,因為IO執行緒並不是瓶頸啊

7. SQL多執行緒?

7.1 沒錯,目前最新的5.6,5.7,8.0 都是在SQL執行緒上實現了多執行緒,來提升slave的併發度

接下來,我們就來一窺MySQL在並行複製上的努力和成果吧

二、重點

是否能夠並行,關鍵在於多事務之間是否有鎖衝突,這是關鍵。 下面的並行複製原理就是在看如何讓避免鎖衝突

三、MySQL5.6 基於schema的並行複製

slave-parallel-type=DATABASE(不同庫的事務,沒有鎖衝突)

之前說過,並行複製的目的就是要讓slave儘可能的多執行緒跑起來,當然基於庫級別的多執行緒也是一種方式(不同庫的事務,沒有鎖衝突)

先說說優點: 實現相對來說簡單,對使用者來說使用起來也簡單

再說說缺點: 由於是基於庫的,那麼並行的粒度非常粗,現在很多公司的架構是一庫一例項,針對這樣的架構,5.6的並行複製無能為力。當然還有就是主從事務的先後順序,對於5.6也是個大問題

話不多說,來張圖好了

四、MySQL5.7 基於group commit的並行複製

slave-parallel-type=LOGICAL_CLOCK : Commit-Parent-Based模式(同一組的事務[last-commit相同],沒有鎖衝突. 同一組,肯定沒有衝突,否則沒辦法成為同一組)
slave-parallel-type=LOGICAL_CLOCK : Lock-Based模式(即便不是同一組的事務,只要事務之間沒有鎖衝突[prepare階段],就可以併發。 不在同一組,只要N個事務prepare階段可以重疊,說明沒有鎖衝突)

group commit,之前的文章有詳細描述,這裡不多解釋。MySQL5.7在組提交的時候,還為每一組的事務打上了標記,現在想想就是為了方便進行MTS吧。

我們先看一組binlog

last_committed=0 sequence_number=1
last_committed=1 sequence_number=2
last_committed=2 sequence_number=3
last_committed=3 sequence_number=4
last_committed=4 sequence_number=5
last_committed=4 sequence_number=6
last_committed=4 sequence_number=7
last_committed=6 sequence_number=8
last_committed=6 sequence_number=9
last_committed=9 sequence_number=10

4.1 Commit-Parent-Based模式

4.2 Lock-Based模式


五、MySQL8.0 基於write-set的並行複製

基於主鍵的衝突檢測(binlog_transaction_depandency_tracking = COMMIT_ORDERE|WRITESET|WRITESET_SESSION,修改的row的主鍵或非空唯一鍵沒有衝突,即可並行)
5.7.22 也支援了 write-set 機制

事務依賴關係:binlog_transaction_depandency_tracking = COMMIT_ORDERE|WRITESET|WRITESET_SESSION

COMMIT_ORDERE: 繼續基於組提交方式
WRITESET: 基於寫集合決定事務依賴
WRITESET_SESSION: 基於寫集合,但是同一個session中的事務不會有相同的last_committed

事務檢測演算法:transaction_write_set_extraction = OFF| XXHASH64 | MURMUR32

MySQL會有一個變數來儲存已經提交的事務HASH值,所有已經提交的事務所修改的主鍵(或唯一鍵)的值經過hash後都會與那個變數的集合進行對比,來判斷改行是否與其衝突,並以此來確定依賴關係

這裡說的變數,可以通過這個設定大小: binlog_transaction_dependency_history_size

這樣的粒度,就到了 row級別了,此時並行的粒度更加精細,並行的速度會更快,某些情況下,說slave的並行度超越master也不為過(master是單執行緒的寫,slave也可以並行回放)

六、如何讓slave的並行複製和master的事務執行的順序一致呢

5.7.19 之後,可以通過設定 slave_preserve_commit_order = 1

官方解釋:

For multithreaded slaves,enabling this variable ensures that transactions are externalized on the slave in the same order as they appear in the slave's relay log.
Setting this variable has no effect on slaves for which multithreading is not enabled.
All replication threads (for all replication channels if you are using multiple replication channels) must be stopped before changing this variable.
--log-bin and --log-slave-updates must be enabled on the slave.
In addition --slave-parallel-type must be set to LOGICAL_CLOCK.
Once a multithreaded slave has been started,transactions can begin to execute in parallel.
With slave_preserve_commit_order enabled,the executing thread waits until all previous transactions are committed before committing.
While the slave thread is waiting for other workers to commit their transactions it reports its status as Waiting for preceding transaction to commit.

大致實現原理就是:excecution階段可以並行執行,binlog flush的時候,按順序進行。 引擎層提交的時候,根據binlog_order_commit也是排隊順序完成

換句話說,如果設定了這個引數,master是怎麼並行的,slave就怎麼辦並行

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對我們的支援。