MySQL並行複製探索!

寫在前面:
對於線上運行主從複製架構的環境而言,相信有不少人和筆者同樣,都或多或少的遇到過主從延遲的問題。以前筆者寫過一篇文章 主從複製延遲緣由剖析 來說解主從複製延遲的緣由,可光是知道緣由還不行,怎麼解決這個主從延遲的問題纔是重頭戲!筆者,帶着這個疑問,在網上也是查閱了諸多資料,而後去其糟粕,根據本身的理解和查閱的資料整理成了本文 MySQL並行複製探索!。事先申明,本文內容是筆者本身的理解,不表明權威性,僅供各位同行作個參考,本身呢,也作個記錄。本着實事求是的原則,對於網上的諸多資料,筆者本身也只是信5分,懷疑5分,就算是官方的資料,有的也有bug不是,只有本身動手實踐過了,才能相信,纔有發言權,其餘的,一切都是虛的!
html


並行複製產生的背景:
由於I/O thread和SQL thread是單線程工做的,而Master是能夠多線程寫入的,因此主從不免形成延遲
基於此,在5.6,5.7,8.0版本都在SQL線程上實現了多線程,來提高slave的併發度
mysql


爲何不是I/O多線程?
I/O不必多線程,由於I/O線程並非瓶頸啊 (沒怎麼理解)
sql


並行複製的目的:
讓Slave SQL線程儘量以多線程工做,解決複製延遲的問題

並行複製實現的前提:
可以進行並行複製,關鍵在於多事務之間是否有鎖衝突
數據庫


MySQL5.6基於schema的並行複製:
應用場景:
比較適用於一個庫中有多個schema的場景
服務器


並行複製的原理:
MySQL5.6開啓並行複製功能後,SQL線程變成coordinator線程,由其判斷是否能夠併發執行,這意味着一個worker線程能夠處理一個數據庫的連續事務,而不用等待其它數據庫完成
若是能夠並行執行,選擇worker線程執行二進制日誌
若是不能夠並行執行,如:DDL或者跨schema操做,則等待全部的worker線程執行完成以後再執行當前日誌
多線程


摘自網上的一張圖片,供參考理解:架構

圖片.png



基於schema的並行複製帶來的問題:
由於MySQL5.6並行複製只是基於schema,但對於單庫多表的複製場景是沒法實現的,甚至性能可能還達不到原來的單線程複製,而在實際工做中單庫多表比多庫多表的場景更爲常見。
MySQL5.6基於schema級別的併發複製能夠解決業務表放在不一樣的DATABASE下同步延遲的問題,可是在實際生產中大部分表仍是放在同一個庫中的,這種狀況即便設置slave_parallel_workers大於0,也沒法進行併發。在高併發的狀況下,依然會形成主從複製延遲

併發

MySQL5.6並行複製開啓:(前提是配置好主從複製環境)app

mysql> stop slave;ide

Query OK, 0 rows affected (0.03 sec)


mysql> set global slave_parallel_workers=8;

Query OK, 0 rows affected (0.05 sec)


mysql> start slave;

Query OK, 0 rows affected, 1 warning (0.07 sec)


參考文檔:

http://blog.itpub.net/23718752/viewspace-2135701/

https://www.cnblogs.com/elontian/p/9989007.html


MySQL5.6並行複製原理圖:


圖片.png


並行複製參數說明:

slave_parallel_workers:
Number of applier threads for executing replication transactions in parallel. A value of 0 disables slave multithreading. Not supported by MySQL Cluster


官方文檔:
https://dev.mysql.com/doc/refman/5.6/en/replication-options-reference.html


MySQL5.7並行複製原理:
基於組複製(group commit)實現

如何知道事務是否在同一組中?
在MySQL 5.7版本中,其設計方式是將組提交的信息存放在GTID中。那麼若是用戶沒有開啓GTID功能,即:將參數gtid_mode設置爲OFF呢?
MySQL 5.7引入了稱之爲Anonymous_Gtid(ANONYMOUS_GTID_LOG_EVENT)的二進制日誌event類型,組提交信息存放在 Anonymous_Gtid 中。


開啓GTID時,每個操做語句(DML/DDL)執行前就會添加一個GTID事件,記錄當前全局事務ID;同時在MySQL 5.7版本中,組提交信息也存放在GTID事件中,有兩個關鍵字段last_committed,sequence_number就是用來標識組提交信息的。在InnoDB中有一個全局計數器(global counter),在每一次存儲引擎提交以前,計數器值就會增長。在事務進入prepare階段以前,全局計數器的當前值會被儲存在事務中,這個值稱爲此事務的commit-parent(也就是last_committed)。last_committed表示事務提交的時候,上次事務提交的編號,若是事務具備相同的last_committed,表示這些事務都在一組內,能夠進行並行的回放。而sequence_number是順序增加的,每一個事務對應一個序列號。


這意味着在MySQL 5.7版本中即便不開啓GTID,每一個事務開始前也是會存在一個Anonymous_Gtid,而這個Anonymous_Gtid事件中就存在着組提交的信息。反之,若是開啓了GTID後,就不會存在這個Anonymous_Gtid了,從而組提交信息就記錄在非匿名GTID事件中。

MySQL如何將這些事務進行分組的?
一個組提交的事務都是能夠並行回放,由於這些事務都已進入到事務的prepare階段,則說明事務之間沒有任何衝突(不然就不可能提交)


MySQL5.7並行複製簡介:
1)MySQL 5.7纔可稱爲真正的並行複製,這其中最爲主要的緣由就是slave服務器的回放與master是一致的,即master服務器上是怎麼並行執行的,那麼slave上就怎樣進行並行回放。再也不有庫的並行複製限制,對於二進制日誌格式也無特殊的要求(基於庫的並行複製也沒有要求)
2)MySQL5.7並行複製支持表級
3)Enhanced Multi-threaded Slaves(MTS

MySQL5.7並行複製參數:
SHOW VARIABLES LIKE 'slave_parallel_%'
Variable_name       Value
slave_parallel_type DATABASE (變量slave-parallel-type能夠有兩個值:DATABASE 默認值,基於庫的並行複製方式;LOGICAL_CLOCK:基於組提交的並行複製方式(基於表)
slave_parallel_workers      0

MySQL 5.7並行複製配置與調優:
# slave
slave-parallel-type=LOGICAL_CLOCK
slave-parallel-workers=16
slave_preserve_commit_order=1
master_info_repository=TABLE
relay_log_info_repository=TABLE
relay_log_recovery=ON

參考文檔:
http://www.javashuo.com/article/p-xgiumuqc-k.html
https://www.imooc.com/learn/589
https://dev.mysql.com/doc/refman/5.7/en/replication-options-slave.html
http://www.ywnds.com/?p=3894

MySQL5.7在線開啓並行複製(多線程複製):
參考視頻:https://www.imooc.com/video/10921


在Slave服務器上中止全部鏈路的複製

stop slave
set global slave-parallel-type=LOGICAL_CLOCK
set global slave-parallel-workers=16
start slave
show processlist(看到16個SQL線程)

MySQL5.7應用事務順序和realy log記錄事務順序不同的問題:MySQL 5.7後的MTS能夠實現更小粒度的並行複製,但須要將slave_parallel_type設置爲LOGICAL_CLOCK,但僅僅設置爲LOGICAL_CLOCK也會存在問題,由於此時在slave上應用事務的順序是無序的,和relay log中記錄的事務順序不同,這樣數據一致性是沒法保證的,爲了保證事務是按照relay log中記錄的順序來回放,就須要開啓參數slave_preserve_commit_order

相關文章
相關標籤/搜索