MySQL 5.7基於組提交的並行複製

參考連接:

http://mysql.taobao.org/monthly/2016/08/01/php

https://www.kancloud.cn/thinkphp/mysql-parallel-applier/45909mysql

 

5.7新版本複製方面的主要優化內容:sql

運維thinkphp

  • 在線啓停GTID
  • 在線配置Replication Filter,無需重啓
  • Change Master到另一個主庫無需中止apply線程
  • Change Master修改一些日誌apply屬性(例如master_delay)無需中止IO線程
  • 增長大量Performance Schema表用於監控複製

新特性服務器

  • Loss-less Semi-sync Replication: 容許在事務提交前等待備庫ACK
  • Semisync容許配置成主庫等待N個ACK才繼續提交,增長可用性
  • 存儲GTID信息到系統表中,這樣備庫若是無級聯的話,就能夠直接關閉備庫的binlog
  • Multi-source Replication:容許從多個主庫複製數據到一臺備庫上
  • Group Replication Plugin,多主結構的集羣管理插件

性能網絡

  • 更好的複製性能(logical_clock):在主庫上可以併發的事務,經過利用Group Commit在日誌中被標記爲能在備庫併發執行。從而得到更好的併發apply效率
  • Binlog Dump線程不受Lock_log鎖影響,預分配並重用用於讀取log event的內存
  • 獨立的ACK線程,用於處理semisync打開場景下備庫返還的ack,保證在等待網絡時不阻塞binlog dump線程,提高了總體併發度。

 

 

logical_clock方便的內容:併發

 

MySQL 5.7纔可稱爲真正的並行複製,這其中最爲主要的緣由就是slave服務器的回放與主機是一致的即master服務器上是怎麼並行執行的slave上就怎樣進行並行回放。再也不有庫的並行複製限制,對於二進制日誌格式也無特殊的要求(基於庫的並行複製也沒有要求)。app

從MySQL官方來看,其並行複製的本來計劃是支持表級的並行複製和行級的並行複製,行級的並行複製經過解析ROW格式的二進制日誌的方式來完成,WL#4648。可是最終出現給小夥伴的確是在開發計劃中稱爲:MTS: Prepared transactions slave parallel applier,可見:WL#6314。該並行複製的思想最先是由MariaDB的Kristain提出,並已在MariaDB 10中出現,相信不少選擇MariaDB的小夥伴最爲看重的功能之一就是並行複製。less

MySQL 5.7並行複製的思想簡單易懂,一言以蔽之:一個組提交的事務都是能夠並行回放,由於這些事務都已進入到事務的prepare階段,則說明事務之間沒有任何衝突(不然就不可能提交)。運維

爲了兼容MySQL 5.6基於庫的並行複製,5.7引入了新的變量slave-parallel-type,其能夠配置的值有:

  • DATABASE:默認值,基於庫的並行複製方式
  • LOGICAL_CLOCK:基於組提交的並行複製方式

支持並行複製的GTID

如何知道事務是否在一組中,又是一個問題,由於原版的MySQL並無提供這樣的信息。在MySQL 5.7版本中,其設計方式是將組提交的信息存放在GTID中。那麼若是用戶沒有開啓GTID功能,即將參數gtid_mode設置爲OFF呢?故MySQL 5.7又引入了稱之爲Anonymous_Gtid的二進制日誌event類型,如:

mysql> SHOW BINLOG EVENTS in 'mysql-bin.000006'; +------------------+-----+----------------+-----------+-------------+-----------------------------------------------+ | Log_name | Pos | Event_type | Server_id | End_log_pos | Info | +------------------+-----+----------------+-----------+-------------+-----------------------------------------------+ | mysql-bin.000006 | 4 | Format_desc | 88 | 123 | Server ver: 5.7.7-rc-debug-log, Binlog ver: 4 | | mysql-bin.000006 | 123 | Previous_gtids | 88 | 194 | f11232f7-ff07-11e4-8fbb-00ff55e152c6:1-2 | | mysql-bin.000006 | 194 | Anonymous_Gtid | 88 | 259 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' | | mysql-bin.000006 | 259 | Query | 88 | 330 | BEGIN | | mysql-bin.000006 | 330 | Table_map | 88 | 373 | table_id: 108 (aaa.t) | | mysql-bin.000006 | 373 | Write_rows | 88 | 413 | table_id: 108 flags: STMT_END_F | ......

這意味着在MySQL 5.7版本中即便不開啓GTID,每一個事務開始前也是會存在一個Anonymous_Gtid,而這GTID中就存在着組提交的信息。

LOGICAL_CLOCK

然而,經過上述的SHOW BINLOG EVENTS,咱們並無發現有關組提交的任何信息。可是經過mysqlbinlog工具,用戶就能發現組提交的內部信息:

root@localhost:~# mysqlbinlog mysql-bin.0000006 | grep last_committed #150520 14:23:11 server id 88 end_log_pos 259 CRC32 0x4ead9ad6 GTID last_committed=0 sequence_number=1 #150520 14:23:11 server id 88 end_log_pos 1483 CRC32 0xdf94bc85 GTID last_committed=0 sequence_number=2 #150520 14:23:11 server id 88 end_log_pos 2708 CRC32 0x0914697b GTID last_committed=0 sequence_number=3 #150520 14:23:11 server id 88 end_log_pos 3934 CRC32 0xd9cb4a43 GTID last_committed=0 sequence_number=4 #150520 14:23:11 server id 88 end_log_pos 5159 CRC32 0x06a6f531 GTID last_committed=0 sequence_number=5 #150520 14:23:11 server id 88 end_log_pos 6386 CRC32 0xd6cae930 GTID last_committed=0 sequence_number=6 #150520 14:23:11 server id 88 end_log_pos 7610 CRC32 0xa1ea531c GTID last_committed=6 sequence_number=7 #150520 14:23:11 server id 88 end_log_pos 8834 CRC32 0x96864e6b GTID last_committed=6 sequence_number=8 #150520 14:23:11 server id 88 end_log_pos 10057 CRC32 0x2de1ae55 GTID last_committed=6 sequence_number=9 #150520 14:23:11 server id 88 end_log_pos 11280 CRC32 0x5eb13091 GTID last_committed=6 sequence_number=10 #150520 14:23:11 server id 88 end_log_pos 12504 CRC32 0x16721011 GTID last_committed=6 sequence_number=11 #150520 14:23:11 server id 88 end_log_pos 13727 CRC32 0xe2210ab6 GTID last_committed=6 sequence_number=12 #150520 14:23:11 server id 88 end_log_pos 14952 CRC32 0xf41181d3 GTID last_committed=12 sequence_number=13 ...

能夠發現較之原來的二進制日誌內容多了last_committed和sequence_number,last_committed表示事務提交的時候,上次事務提交的編號,若是事務具備相同的last_committed,表示這些事務都在一組內,能夠進行並行的回放。例如上述last_committed爲0的事務有6個,表示組提交時提交了6個事務,而這6個事務在從機是能夠進行並行回放的。

上述的last_committed和sequence_number表明的就是所謂的LOGICAL_CLOCK。先來看源碼中對於LOGICAL_CLOCK的定義:

class Logical_clock { private: int64 state; /* Offset is subtracted from the actual "absolute time" value at logging a replication event. That is the event holds logical timestamps in the "relative" format. They are meaningful only in the context of the current binlog. The member is updated (incremented) per binary log rotation. */ int64 offset; ......

state是一個自增的值,offset在每次二進制日誌發生rotate時更新,記錄發生rotate時的state值。其實state和offset記錄的是全局的計數值,而存在二進制日誌中的僅是當前文件的相對值。使用LOGICAL_CLOCK的場景以下:

class MYSQL_BIN_LOG: public TC_LOG { ... public: /* Committed transactions timestamp */ Logical_clock max_committed_transaction; /* "Prepared" transactions timestamp */ Logical_clock transaction_counter; ...

能夠看到在類MYSQL_BIN_LOG中定義了兩個Logical_clock的變量:

  • max_c ommitted_transaction:記錄上次組提交時的logical_clock,表明上述mysqlbinlog中的last_committed
  • transaction_counter:記錄當前組提交中各事務的logcial_clock,表明上述mysqlbinlog中的sequence_number
相關文章
相關標籤/搜索