官方文檔: https://mariadb.com/kb/en/mariadb/parallel-replicationhtml
從10.0.5版本開始,MariaDB開始支持並行複製mysql
MariaDB10.0的從服務器能並行的執行查詢和複製操做,這篇文章將會解釋是如何實現的和你能夠作的調優。sql
注意:主從服務器上的 MariaDB 的版本必須是10.0.5和10.0.5的之後的版本,才能啓用並行複製安全
Parallel replication overview -- 並行複製概述服務器
MariaDB 的複製經過三步完成:session
1.從服務的IO線程去主庫上讀取變動事件,並把讀取的事件順序放到relay log中app
2.從服務器的SQL線程一次讀取relay log中的一個事件dom
3.SQL線程依次應用relay log中的事件ide
MariaDB 10以前的版本中,第三步是經過SQL線程來執行的,這意味着,一次只能執行一個事件,複製本質上是單線程的。性能
MariaDB 10以後的版本中,第三步能夠經過一組相互獨立的複製線程,由於能夠一次並行複製多個事件,提高了複製性能。
How to enable parallel slave -- 如何開啓並行複製
在 my.cnf 指定 slave-parallel-threads = n 做爲參數傳遞給MySQL.
並行複製也能夠用於多源複製鏈接設置 "@@connection_name.slave-parallel-mode" 設置爲 none, 即 set @@connection_name.slave-parallel-mode = none
slave_parallel_threads 的值決定了池中會有多少個工做線程會被建立用來在從服務器上執行並行複製事件
若是值爲0,默認採用舊的複製方式(即slave的SQL線程來重放event事件)
一般來說,若是值爲非0,應該設置爲多源主服務器鏈接數的至少兩倍。一個鏈接用一個工做線程的意義不大,由於這不但會增長內部線程通信(即SQL線程和工做線程之間的通信)的負擔,並且一個鏈接使用一個工做線程的時候,事件不能被並行複製。
slave_parallel_threads 的值可進行動態調整,便可在不重啓MySQL的狀況下,進行更改,可是更改的時候,全部的從庫鏈接都要被中止。
What can be run in parallel -- 如何運行並行複製
並行複製的方式有哪些?
in-order 有序 和 out-of-order 無序兩種方式
有序方式
並行執行事務,可是對commit順序進行排序,以確保從庫上事務提交和主庫上事務提交順序一致。只有那些被自動確認爲不會引發衝突的事務纔會被並行執行,也就是說,並行複製對應用來講,是徹底透明的。
無序方式
無序意味着在從庫上執行和提交事務的順序跟主庫可能不一致,也就是說,應用必需要具有容忍主從服務器上數據更新順序不一致的問題,同時這種方式要求應用來確保事務之間的沒有衝突。無序方式只在GTID模式和應用明確指定使用無序的時候纔會被使用, 複製域屬於gtid的一部分。
Conservative mode of in-order parallel -- 樂觀並行複製模式(optimistic)
Optimistic模式,從MariaDB 10.1.3版本開始支持。
這種模式提供了大量的並行應用slave,同時從應用程序的角度來看,仍然保留精確的事務語義。
開啓使用配置選項 --slave-parallel-mode=optimistic.
任何事務DML(插入/更新/刪除)能夠並行運行,達到限制@@slave_domain_parallel_threads。這可能在slave致使衝突,若是兩個事務試圖修改同一行,檢測到任何這樣的衝突,而且兩個事務的後者被回滾,容許前者繼續, 一旦前者已經完成,後者的事務從新嘗試。
Optimistic模式適用於這種方式,由於服務器會發生一些衝突樂觀的假定,這額外的工做花了回滾後從新事務衝突時從運行大部分事務得到合理的並行。
有一些啓發,試圖避免沒必要要的衝突,若是在master上一個事務執行了一個行鎖等待。它不會再並行運行slave,
事務也能夠明確在master上標識爲潛在的衝突,經過設置變量@@skip_parallel_replication。這種啓發式可能在之後加入MariaDB版本(如今還不支持)
這是接下來的選項--slave-parallel-mode 叫 侵略性"aggressive"模式。當這些啓發式唄禁用,容許更多的事務將被應用在並行。
非事務DML和DDL不安全的樂觀應用並行,由於它不能再衝突的狀況下,回滾。所以,在樂觀的模式下,非事務性的(如MyISAM)更新不適用於並行或者早期的事件。(不過,可能適用於並聯一個MyISAM更新後會更新),DDL語句不適用於任何其餘事務,或早或晚。
不一樣的事務類型能夠在mysqlbinlog輸出肯定,例如:
#150324 13:06:26 server id 1 end_log_pos 6881 GTID 0-1-42 ddl
...
#150324 13:06:26 server id 1 end_log_pos 7816 GTID 0-1-47
...
#150324 13:06:26 server id 1 end_log_pos 8177 GTID 0-1-49 trans
/*!100101 SET @@session.skip_parallel_replication=1*//*!*/;
...
#150324 13:06:26 server id 1 end_log_pos 9836 GTID 0-1-59 trans waited
gtid 0-1-42標明DDL。gtid 0-1-47被標記爲非事務DML。而gtid 0-1-49是事務性的DML("trans" 關鍵字),另外,gtid 0-1-49在master上運行@@ skip_parallel_replication,gtid 0-1-59是事務型的,在master上有一排等待DML鎖。("waited" 關鍵字)。
Conservative mode of in-order parallel -- 保守並行複製(conservative)模式
默認是conservative模式,在10.0版本中惟一可用的模式,可使用 --slave-parallel-mode=conservative 開啓。
在conservative模式中,並行複製在master上使用"組提交「,以發現潛在的並行應用事件的slave,
在mater上若是兩個事物提交在一組,他們都寫進同一個commit id,此類事件的binlog必定不會互相沖突,他們能夠計劃安排由複製到運行在不一樣的線程中。
兩個在主上單獨提交的事務可能會發生衝突(如,修改同一個表的一行)。所以,應用第二個事務的worker不會當即開始。
可是等到第一個事務開始提交步驟以後,在這一點上,啓動第二個事務是安全的,由於它不能再擾亂第一個的執行。
這是mysqlbinlog輸出的一個例子,顯示gtid events都標有commit id,gtid 0-1-47 沒有提交ID,不能並行運行,
gtid 0-1-48和0-1-49有相同的commit id 630,能夠在另外一個slave上並行複製。
binlog信息以下:
#150324 12:54:24 server id 1 end_log_pos 20052 GTID 0-1-47 trans
...
#150324 12:54:24 server id 1 end_log_pos 20212 GTID 0-1-48 cid=630 trans
...
#150324 12:54:24 server id 1 end_log_pos 20372 GTID 0-1-49 cid=630 trans
在任何一種狀況下,當兩個事務到達低級別提交的點,並肯定提交順序時,這兩個提交以相同的順序發生在mater上,這樣操做對應用程序是透明的。
若是在一個組提交中提交了更多的事務,則能夠高度地增長對slave的並行複製的機會。
這個能夠調整使用binlog_commit_wait_count和binlog_commit_wait_usec變量,例如,若是應用程序在master能夠容忍額外延遲50毫秒,你能夠設置binlog_commit_wait_usec = 50000和binlog_commit_wait_count = 20,在一個可用的時間,並行複製可得到高達20的事務處理。
不太小心不要設置binlog_commit_wait_usec過高,由於這可能致使應用程序會放緩,運行大量的串行小事務一個接一個的。
請注意:在master上即便沒有組提交的並行性,仍然有個機會,提高並行速度。
因爲不一樣事務的實際提交步驟能夠運行。在slave上特別有效,binlog開啓(log_slave_updates=1)
甚至若是slave配置崩潰修復安全(sync_binlog=1 and innodb_flush_log_at_trx_commit=1),這種組提交可能在slave上
在--slave-parallel-mode=minimal模式下,僅僅事務提交步驟被並行應用。全部其餘事務複製都是連續發生的。
Out-of-order parallel -- 無序並行複製
無序並行複製只使用在GTID模式下,當使用不一樣的複製域GTID時,複製域是有DBA/應用程序中使用的變量gtid_domain_id.
在並行複製中有兩個事務gtids,不一樣domain_id定於不一樣的線程,並容許執行徹底獨立於此,它是應用程序的責任,只爲那些真正獨立的事務設置不一樣的domain_ids,
並保證不會相互衝突,應用程序還必須正常工做,即便事務中有不一樣的domain_id,被視爲不一樣的順序呢,在slave和master之間,或者在不一樣的slave中。
因爲應用程序能夠顯式地提供更多並行運行事務的機會。而不是服務器能夠自動肯定的,出於事務並行複製的順序並行複製可能自動本身肯定本身
一個簡單但有效的用法是運行單獨的複製域中的長時間運行的語句,如「更改表」。這容許複製其餘事務繼續進行不間斷:
SET SESSION gtid_domain_id=1
ALTER TABLE t ADD INDEX myidx(b)
SET SESSION gtid_domain_id=0
一般,一個長時間運行的ALTER TABLE語句或者 其餘查詢,將會中止全部後面的事務。會引起slave落後於master至少須要很長的時間去執行這個運行時間很長的查詢。
經過無序並行複製,設置複製domain id。是能夠避免的。當運行ALTER TABLE時,DBA/應用程序必須確保沒有衝突的事務將被複制。
出於無序並行複製的另外一個常見的條件,是於多源複製有關的。假設咱們有兩個不一樣的master M1 M2,咱們利用多源複製S1做爲一個M1和M2的slave,S1將收到從M2事件並行M1接收事件。
若是咱們如今有三分之一級的奴隸,從S1 S2複製master,咱們但願S2也可以應用事件起源於M1與M2平行事件起源於。這能夠從順序並行複製來實現,經過設置在M1和M2 gtid_domain_id不一樣。
請注意,沒有什麼特殊限制,可使用無序的並行複製,這樣的操做能夠在同一個database/schema,甚至在同一個table中,惟一的限制是,操做必須不衝突,這是他們必須可以以任何順序應用,並最終得到相同的結果。
當使用了無序並行複製時,
當前slave position就是 master 位置
在master binlog在任何一個時間,成爲多維 - 每一個複製域能夠達到一個不一樣的點,
當前的position能夠在gtid_slave_pos變量看到。當slave被中止、重啓、或者切換複製從不一樣master 使用CHANGE MASTER時,MariaDB自動處理重啓每一個複製域在binlog適當點。
當--slave-parallel-mode=minimal(或none)模式,無序並行複製是關閉的。
Checking worker thread status in SHOW PROCESSLIST -- 檢查顯示列表的線程狀態
在show processlist中,工做線程將會列出"system user",他們的狀態將顯示他們目前正在進行的查詢,或者它能夠顯示其中一個:
"Waiting for work from main SQL threads". "等待工做從主要的SQL線程"。
這意味着工做線程空閒,沒有工做可用於它的時刻。
"Waiting for prior transaction to start commit before starting next transaction". "等待以前的事務開始下一次事務開始以前提交"。
這意味着,前一批提交的事務在主必須完成第一個。這個工做線程在等待它發生以前,它能夠開始工做在下面的一批。
This worker thread is waiting for that to happen before it can start working on the following batch.
"Waiting for prior transaction to commit". 」等待優先事務提交「。
這意味着事務已被工做線程執行了,爲了確保訂單提交,工做線程等待提交,知道上一次事務準備在它以前提交爲止。
Expected performance gain -- 性能預期測試的文章
這裏有一篇關於使用並行複製時,改進後高達10倍的性能文章
文章地址: http://kristiannielsen.livejournal.com/18435.html。
slave-parallel-max-queued配置參數:
變量slave_parallel_max_queued是惟一有意義的,前提並行複製技術被使用(slave_parallel_threads參數大於0時),當並行複製被使用時, SQL線程會預讀relay-log中的event,隊列時間放在內存中,在並行複製中,同時尋找並行執行事件的機會。@@slave_parallel_max_queued變量設置爲SQL 線程將在預讀多少內存限制的日誌,尋找這樣的機會。每一個線程是有限制的,所以,此次預讀的值是設置@@slave_parallel_threads變量值得來的
若是這個值設置的過高,而且slave落後於master太遠(如千兆字節的binlog),而後SQL線程能夠快速讀,填補大量內存的binlog事件比工做線程消耗的更快
另外一方面,若是值定的過低,SQL線程可能沒有足夠的空間來保持足夠的事件隊列忙的線程,這可能下降性能。
注意,@@slave_parallel_max_queued不是硬性限制,由於binlog事件當前執行老是須要保存在內存中,
例如,每一個工做者線程至少有兩個事件老是能夠在內存中排隊,無論slave_parallel_threads是多
一般,slave_parallel_threads應該設置的足夠大,SQL線程利用全部可能的並行性能夠預讀的足夠遠的binlog,在正常操做中,slave將不但願落後太遠,所以不會將大量數據隊列有必要的放在內存中的。因此slave_parallel_threads可能設置的至關高(如幾百KB)不限制吞吐量。它應該被設置的足夠低,slave_parallel_threads * slave_parallel_max_queued 不會形成服務器內存不足。
slave_domain_parallel_threads配置參數:
在全部多源主鏈接中共享複製工做線程池,在全部能夠在並行使用順序複製的複製域中。
若是一個主鏈接或者一個複製域 當前正在執行處理一個長時間的查詢,可能它將分配在池中的全部工做線程,只能等待讓他們長時間運行的查詢完成。
拖延任何master主庫鏈接或者複製域,這將不得不等待複製域工做線程變得空閒。
能夠經過slave_domain_parallel_threads變量設置的值避免低於slave_parallel_threads設置的值,
當設置不等於0時,一個主鏈接中的每一個複製域均可以保留至多一個時間段的多個線程,
其他的,達到slave_parallel_threads參數的值,在並行複製中無其餘主鏈接或者複製域去使用。
slave_domain_parallel_threads變量是能夠動態修改的,能夠在不重啓服務的狀況下更改。全部的slave必須中止掉更改。