MySQL併發複製系列三:MySQL和MariaDB實現對比

沃趣科技發表於2016-01-13

併發複製(Parallel Replication 系列三:MySQL 5.7 MariaDB 10parallel replication對比

作者:沃趣科技MySQL資料庫工程師  麻鵬飛


        經過上兩篇關於MySQL/MariaDB 的Binary Log Group Commit的發展歷程和enhanced multi-threaded slave的介紹,相信大家對MySQL 基於Binay Log 的replication的原理以及為了解決主備資料複製延遲問題而引入的enhanced multi-threaded slave 功能,支援從庫多執行緒併發回放主庫提交的事務有了更深入的瞭解。同時為了更好的發揮MySQL 5.7/MariaDB 10 併發複製的效能,兩個版本都在主庫Binary Log Group Commit的階段做了更加深入的優化。

        無論是MySQL還是MariaDB在Binary Log Group Commit優化的目的都是:使高併發下的事務儘可能的在同一個時間點提交,然後用一次fsync()的操作將這一組的Binary log快取的資料寫入磁碟。當併發事務可以在同一個時間提交,說明每個執行緒所執行的事務之間沒有鎖衝突(如果有鎖衝突,併發的事務將無法在同一個時刻提交),那麼意味著這一組併發提交的事務在slave機器上能併發重放主庫提交的事務,所以我們只需要在master機器對二進位制日誌進行Group Commit的時候標記上組提交相關資訊,slave機器就可以安全的併發執行主庫提交的事務。

我們來看一個例子:

事務T1、T2(start transaction)開始事務,落後於事務T3、T4的(start transaction)開始時間,但是這一組事務都在C(commit)時間點提交事務,所以這一組事務(T1、T2、T3、T4)將在master機器上進行Binary Log group Commit,然後該二進位制日誌推送到slave機器上時可以併發執行這一組被標記的事務。

原理:

       從上面的例子可以看出,併發執行緒執行不同的事務只要在同一時刻能夠commit(說明執行緒之間沒有鎖衝突),那麼master節點就可以將這一組的事務標記並在slave機器上安全的進行併發重放主庫提交的事務。所以儘可能的使所有執行緒能在同一時刻提交可以極大的提高slave機器併發執行事務的數量使主備資料同步。

      在上一篇文章提到過:MySQL/MariaDB開啟Binary Log日誌後使進位制日誌寫入順序和儲存引擎提交順序保持一致,Binary Log Group Commit分為三個過程:
圖1: Binary Log Group Commit 三個階段

在 Flush stage:所有已經註冊執行緒都將寫入binary log快取

在Sync stage :binary log快取的資料將會sync到磁碟,當sync_binlog=1時所有該佇列事務的二進位制日誌快取永久寫入磁碟

在 Commit stage:    leader根據順序呼叫儲存引擎提交事務。

那麼為了使更多的併發執行緒事務能夠視為在同一個時刻commit即在Sync階段(調fsync()把binary log檔案系統快取日誌永久刷入磁碟檔案)master機器標記併發提交的事務為同一組事務的資訊寫入binary log日誌中。我們可以在Flush Stage將註冊為leader的執行緒帶領更多的follower執行緒到Sync stage進行一次fsync()的操作,來增加Binary Log Group Commit的數量。

如下圖:

       當前MySQL/MariaDB資料庫例項上執行三個執行緒分別提交T1、T2、T3事務,T1事務的執行緒率先提交進入第一階段Flush stage佇列,發現該佇列是空佇列故註冊成leader,與此同時T2事務進入Flush stage成為該佇列的follower等待leader調配,事務T1的leader帶領T2事務進入Sync stage進行一次fsync()操作那麼T1、T2在binary log進行一次group commit。
       在二進位制日誌內標記了這一組事務。之後T3執行緒的事務隨後進入了binary log提交的過程。


2: 組提交過程


 MariaDB 10通過@@binlog_commit_wait_count and @@binlog_commit_wait_usec 兩個引數設定,既事務commit階段的時候至少等binlog_commit_wait_usec毫秒直到有binlog_commit_wait_count個數時進行一次組提交,來提高每組事務中的事務數量,並可以通過查詢狀態變數@@binlog_commit和@@binlog_group_commit來查引數來檢視當前binary log group commit比例。

 MySQL5.7通過引入 binlog_group_commit_sync_delay和 binlog_group_commit_sync_no_delay_count引數即提高binary log組提交併發數量,既MySQL等待binlog_group_commit_sync_delay毫秒的時間直到binlog_group_commit_sync_no_delay_count個數時進行一次組提交。


實現:

 Binary Log Group Commit在MySQL 5.7和MariaDB 10 中是預設開啟不需要配置任何資訊,且在binary log中標記的組提交資訊依賴於GTID,而MySQL和MariaDB的GTID組成和實現方式不一樣,這裡我們簡單梳理下。

        在MySQL 5.7版本由於Binary Log Group Commit是預設開啟的,所以即使你不開啟gtid_mode在配置檔案中,binary log的內容中同樣也有GTID 資訊只不過標記的資訊是"ANONYMOUS"

>    show binlog events in 'mysql-bin.000004';擷取一段資訊

1.  ...............
| mysql-bin.000004 | 3571 | Anonymous_Gtid |     15112 |        3636 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'          |

2.  | mysql-bin.000004 | 3636 | Query          |     15112 |        3712 | BEGIN                   |

3.  | mysql-bin.000004 | 3712 | Rows_query     |     15112 |        3763 | # INSERT INTO t1 () VALUES ()                 |

4.  | mysql-bin.000004 | 3763 | Table_map      |     15112 |        3807 | table_id: 108 (db2.t1)                        |

5.  | mysql-bin.000004 | 3807 | Write_rows     |     15112 |        3847 | table_id: 108 flags: STMT_END_F               |

6.  | mysql-bin.000004 | 3847 | Xid            |     15112 |        3878 | COMMIT /* xid=33 */                           |
.................

>     mysqlbinlog -vvv mysql-bin.00004 | less

1.  #151231 14:34:03 server id 15112  end_log_pos 2408 CRC32 0x5586fe71     Anonymous_GTID  last_committed=6        sequence_number=8

2.  SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;

3.  # at 2408

4.  #151231 14:34:03 server id 15112  end_log_pos 2484 CRC32 0x748efb17     Query   thread_id=11    exec_time=0     error_code=0

5.  SET TIMESTAMP=1451543643/*!*/;

6.  BEGIN

7.  ..


         MariaDB的GTID同樣也是預設開啟且GTID是由Domain ID、Server ID和transaction Sequence Number組成:


   圖3 MariaDB GTID組成

>    show binlog events in 'mysql-bin.000003';擷取一段資訊

1.  .......
| mysql-bin.000003 |  335 | Gtid              |     15102 |         377 | BEGIN GTID 0-15102-64139                      |

2.  | mysql-bin.000003 |  377 | Table_map         |     15102 |         434 | table_id: 18 (test.sbtest1)                   |

3.  | mysql-bin.000003 |  434 | Write_rows_v1     |     15102 |         657 | table_id: 18 flags: STMT_END_F                |

4.  | mysql-bin.000003 |  657 | Xid               |     15102 |         688 | COMMIT /* xid=16 */                           |

5.  | mysql-bin.000003 |  688 | Gtid              |     15102 |         732 | BEGIN GTID 0-15102-64140 cid=20               |

6.  | mysql-bin.000003 |  732 | Table_map         |     15102 |         789 | table_id: 19 (test.sbtest6)                   |

7.  | mysql-bin.000003 |  789 | Write_rows_v1     |     15102 |        1012 | table_id: 19 flags: STMT_END_F                |

8.  | mysql-bin.000003 | 1012 | Xid               |     15102 |        1043 | COMMIT /* xid=20 */                           |

9.  | mysql-bin.000003 | 1043 | Gtid              |     15102 |        1087 | BEGIN GTID 0-15102-64141 cid=20               |

10. | mysql-bin.000003 | 1087 | Table_map         |     15102 |        1145 | table_id: 20 (test.sbtest12)                  |

11. | mysql-bin.000003 | 1145 | Write_rows_v1     |     15102 |        1368 | table_id: 20 flags: STMT_END_F                |

12. | mysql-bin.000003 | 1368 | Xid               |     15102 |        1399 | COMMIT /* xid=21 */                           |
......


>    mysqlbinlog -vvv mysql-bin.00003  | less

1.     .......

2.     # at 1754

3.  #160104 15:16:46 server id 15102  end_log_pos 1798 CRC32 0x26104c0b     GTID 0-15102-64143 cid=20 trans

4.  /*!100001 SET @@session.gtid_seq_no=64143*//*!*/;

5.  BEGIN

6.  /*!*/;

7.  # at 1798

8.  #160104 15:16:46 server id 15102  end_log_pos 1856 CRC32 0x2c994f5a     Table_map: `test`.`sbtest12` mapped to number 20

9.  # at 1856

10. #160104 15:16:46 server id 15102  end_log_pos 2079 CRC32 0x02b5a694     Write_rows: table id 20 flags: STMT_END_F

11.  

12.  BINLOG '

13.  .........


結論:

        MySQL 5.7 / MariaDB 10的parallel replication都是基於主庫上Binary Log Group Commit。

        MySQL:  主庫併發提交的事務group commit寫入binary log日誌中,當事務被標記的  last_committed=N的值相同時(通過binlog_group_commit_sync_delay、 binlog_group_commit_sync_no_delay_count引數設定提高併發事務數量),可以在slave節點併發回放主庫提交的事務。

    MariaDB: 主庫併發提交的事務group commit寫入binary log日誌中,當事務被標記的 cid=N 的值相同時(通過 binlog_commit_wait_count、binlog_commit_wait_usec引數設定提高併發事務數量),可以在slave節點併發回放主庫提交的事務。


Reference:http://geek.rohitkalhans.com/2013/09/enhancedMTS-deepdive.html

 




 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28218939/viewspace-1975856/,如需轉載,請註明出處,否則將追究法律責任。

相關文章