mysql主從複製

一:mysql複製默認以什麼方式進行、複製粒度html

二:mysql複製的優點mysql

三:mysql複製的方法sql

四:mysql複製的多種類型數據庫

五:記錄binlog的三種格式安全

六:mysql基於binlog複製的原理以及搭建過程服務器

七:mysql複製相關的參數多線程

八:延遲複製的原理以及搭建過程併發

九:半同步複製的原理以及搭建過程app

十:基於GTID複製的原理、搭建過程以及限制條件異步

 

•MySQL複製容許將主實例(master)上的數據同步到一個或多個從實例(slave)上,默認狀況下複製是異步進行的,從庫也不須要一直鏈接到主庫來同步數據

• MySQL複製的數據粒度能夠是主實例上全部的數據庫,也能夠是指定的一個或多個數據庫,也能夠是一個數據庫裏的指定的表

• MySQL複製所帶來的優點在於:
• 擴展能力:經過複製功能能夠將MySQL的性能壓力分擔到一個或多個slave上。這要求全部的寫操做和修改操做都必須在Master上完成,而讀操做能夠被分配到一個或多個slave上。
將讀寫分離到不一樣服務器執行以後,MySQL的讀寫性能獲得提高
• 數據庫備份:因爲從實例是同步主實例的數據,因此能夠將備份做業部署到從庫
• 數據分析和報表:一樣,一些數據分析和報表的實現能夠在從實例執行,以減小對主庫的性能影響
• 容災能力:能夠在物理距離較遠的另外一個數據中心創建一個slave,保證在主實例所在地區遭遇災難時,在另外一個數據中心能快速恢復

MySQL複製有兩種方法
• 傳統方式:基於主庫的bin-log將日誌事件和事件位置複製到從庫,從庫再加以應用來達到主從同步的目的
• Gtid方式:global transaction identifiers是基於事務來複制數據,所以也就不依賴日誌文件,同時又能更好的保證主從庫數據一致性

MySQL複製有多種類型:
• 異步複製:一個主庫,一個或多個從庫,數據異步同步到從庫
• 同步複製:在MySQL Cluster中特有的複製方式
• 半同步複製:在異步複製的基礎上,確保任何一個主庫上的事務在提交以前至少有一個從庫已經收到該事務並日志記錄下來
• 延遲複製:在異步複製的基礎上,人爲設定主庫和從庫的數據同步延遲時間,即保證數據延遲至少是這個參數

• 並行複製:SQL線程實現了多線程,來提高slave的併發度

 

MySQL複製有三種核心格式
• 基於語句的複製(statement based replication):基於主庫將SQL語句寫入到bin log中完成複製
• 基於行數據的複製(row based replication):基於主庫將每個行數據變化的信息做爲事件寫入到bin log中完成日誌
• 混合複製(mixed based replication):上述二者的結合。默認狀況下優先使用基於語句的複製,只有當部分語句若是基於語句複製不安全的狀況下才會自動切換爲基於行數據的複製

mysql複製的工做原理:

MySQL複製涉及三個線程,其中一個在主庫,另兩個在從庫
• binlog dump thread:在主庫建立,用來在從庫連接過來時發送bin log的內容
• slave io thread:在備庫建立,用來鏈接主庫並請求發送新的bin log內容。該線程讀取主庫的bin log dump線程發送的更新內容並將此內容複製到本地的relay log中
• Slave sql thread:在備庫建立,讀取slave io線程在本地relay log中的內容並在本地執行內容中的事件

MySQL基於binlog的複製

基於binary log的複製是指主庫將修改操做寫入到bin log中,從庫負責讀取主庫的bin log,並在本地複製一份,而後將裏面的操做在從庫執行一遍,每一個從庫會保存目前讀取主庫日誌的文件名和日誌位置主庫和每一個從庫都必須有一個惟一ID,叫server-id配置在配置文件中

傳統主從環境的搭建步驟
主庫:
1.安裝完成mysql
2.修改主機的配置文件打開binlog
server-id=1 ##取值範圍 1~2^32-1
log-bin=/dbdata/data/bin-log
log-bin-index=/dbdata/data/bin-log.index
3.建立同步帳號
CREATE USER 'repl'@'192.168.237.%' IDENTIFIED BY 'mysql';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.237.%';
4.在從庫用用同步帳號登陸主庫測試帳號
5.備份全庫並把備份文件copy到從庫恢復(備份以前全庫加鎖;flush tables with read lock;) 生產環境中不適用lock   --single-transaction --master-data=2;
6.記錄show master status \G 位置

從庫:
1.修改從庫的配置文件
server-id=2
relay-log=/dbdata/data/relay-log
relay-log-index=/dbdata/data/relay-log.index
2. CHANGE MASTER TO
MASTER_HOST=‘master_host_name’, ##主庫的主機名
MASTER_PORT=port_number ##主庫的端口號
MASTER_USER=‘replication_user_name’, ##複製的數據庫用戶名
MASTER_PASSWORD=‘replication_password’, ##複製的用戶密碼
MASTER_LOG_FILE=‘recorded_log_file_name’, ##主庫的日誌文件名
MASTER_LOG_POS=recorded_log_position; ##主庫的日誌文件位置
例:
CHANGE MASTER TO
MASTER_HOST='192.168.10.241',
MASTER_PORT=3306,
MASTER_USER='repl',
MASTER_PASSWORD='mysql',
MASTER_LOG_FILE='mysql-bin.000013',
MASTER_LOG_POS=154;
3.start slave;

• 查看主備庫複製是否正常:

• 在slave上執行show slave status\G命令

seconds_behind_master 指的是什麼意思?從庫延遲時間?

官網解釋:

 

seconds_Behind_Master: The number of seconds that the slave SQL thread is behind processing the master binary log
也就是說,是SQL thread在執行IO thread dump下來的relay log的時間差。你們都知道relay log中event記錄的時間戳是主庫上的時間戳,而SQL thread的時間戳是從庫上的,也就是說,若是主庫和從庫的時間是一致的,那麼這個SBM表明的確實是從庫延後主庫的一個時間差

 

 

 

 

複製相關的參數

• log_slave_updates:該參數用來控制是否將收到的主庫的更新數據的語句也記錄在slave本身的bin log中。正常狀況下是不須要記錄的,但若是是想建立級聯複製關係,好比A -> B -> C,這其中B既要做爲A的從庫,也要做爲C的主庫,則須要既開啓log-bin參數,也要開啓log_slave_updates參數

• replicate-do-db:該參數用來指定須要複製的數據庫

• replicate-ignore-db:該參數決定了忽略指定數據庫的複製,其行爲和replicate-do-db正好相反

• replicate-do-table=db_name.tbl_name:經過該參數告知slave的SQL thread僅複製指定表上的數據。若是有多個表,則該參數要使用屢次

• replicate-ignore-table=db_name.tbl_name:經過該參數告知slave的SQL thread將指定表上的數據過濾掉

• replicate-wild-do-table=db_name.tbl_name:經過該參數告知SQL的SQL thread僅複製符合匹配的表,可使用_和%做爲通配符。好比replicate-wild-dotable=foo%.bar%表示複製以foo打頭的數據庫下全部bar打頭的表數據。若是是replicate-wild-do-table=foo%.%,則表示即複製foo打頭的全部表的數據,也複製create/drop/alter database foo打頭的命令

• replicate-wild-ignore-table=db_name.tbl_name:經過該參數告知SQL的SQL thread過濾掉符合匹配的表

• slave-parallel-workers: 該參數決定了slave上啓動多個SQL thread線程來並行應用數據的默認值是0表明不容許並行,取值範圍能夠是0~1024

• skip-slave-start :該參數決定了在MySQL啓動時是否先不啓動slave線程,即暫停複製

• slave-parallel-type=type :該參數決定了當啓動了並行以後,採用什麼粒度的並行方式。默認值database表示按照不一樣的數據庫執行並行LOGICAL_CLOCK則表示按照在binlog中的一組提交的事務做爲並行粒度

• slave-skip-errors=[err_code1,err_code2,...|all|ddl_exist_errors]:該參數決定了當slave的SQL thread執行過程當中碰到何種錯誤時能夠忽略並繼續接下來的數據複製。正常狀況下當有錯誤發生時,複製會中止而須要人工干預修復才能繼續進行。除非很是自信能夠忽略某些錯誤,不然不要使用這個參數,否則會致使雖然複製執行正常,但其實內部的數據已經徹底不一致

• sql_slave_skip_counter表明在非GTID複製環境下,經過設置此參數來跳過多少個複製事件。設置完該參數並不是當即生效,而是要等待下次start slave命令的執行生效,並將該參數再次設置爲0

• binlog-do-db=db_name: 該參數決定了哪些庫下的修改會被記錄到bin log中。其行爲與replicate-do-db類型,在基於SQL語句複製的環境下,只記錄在當前數據庫下的修改

• binlog-ignore-db=db_name:該參數決定了在bin log中忽略的數據庫,其行爲與replicate-ignore-db類型

• binlog_format:該參數決定了bin log中記錄的格式

MySQL延遲複製

延遲複製是指定從庫對主庫的延遲至少是指定的這個間隔時間,默認是0秒。能夠經過change master to命令來指定CHANGE MASTER TO MASTER_DELAY = N;
其原理是從庫收到主庫的bin log以後,不是當即執行,而是等待指定的秒數以後再執行

延遲複製的使用場景好比:
確保在主庫上被錯誤修改的數據能及時找回
測試在從庫IO集中在恢復bin log過程當中對應用程序的訪問影響,保留一份若干天前的數據庫狀態,和當前狀態能夠作對比
show slave status中SQL_Delay值代表了設置的延遲時長

MySQL半同步複製

默認建立的MySQL複製是異步的,意味着主庫將數據庫修改事件寫入到本身的bin log,而並不知道從庫是否獲取了這些事件並應用在本身身上。因此當主庫崩潰致使要主從切換時,有可能從庫上的數據不是最新的

從5.7版本開始MySQL經過擴展的方式支持了半同步複製當主庫執行一個更新操做事務時,提交操做會被阻止直到至少有一個半同步的複製slave確認已經接收到本次更新操做,主庫的提交操做纔會繼續,半同步複製的slave發送確認消息只會在本次更新操做記錄已經記錄到本地的relay log以後,若是沒有任何slave發送確認消息而致使超時時,半同步複製會轉換成異步複製

半同步複製會對MySQL性能產生影響,由於主庫的提交動做只有在收到至少一個從庫的確認消息以後才能執行。但這個功能是性能和數據可靠性方面的權衡

rpl_semi_sync_master_wait_point參數用來控制半同步複製的行爲:

AFTER_SYNC
AFTER_COMMIT 

須要配置的系統參數包括:
rpl_semi_sync_master_enabled:在主庫配置,確保主庫的半同步複製功能開啓
rpl_semi_sync_master_timeout:配置主庫等待多少毫秒時間來保證接收備庫的確認消息,當超過這個時間時,半同步變成異步方式
rpl_semi_sync_slave_enabled:在從庫配置,確保從庫的半同步複製功能開啓

主庫【】
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
SET GLOBAL rpl_semi_sync_master_enabled = 1;
SET GLOBAL rpl_semi_sync_master_timeout = N; ##N是毫秒,默認是10000,表明10秒
從庫【】
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
SET GLOBAL rpl_semi_sync_slave_enabled =1;
需在從庫重啓slave線程

半同步複製監控參數:

Rpl_semi_sync_master_clients:檢查半同步的slave個數
Rpl_semi_sync_master_status:1表示主庫的半同步功能開啓而且運行正常,0表示主庫的半同步功能關閉或者半同步複製已經變成了異步複製
Rpl_semi_sync_master_no_tx:表示有多少提交沒有收到slave的確認消息
Rpl_semi_sync_master_yes_tx:表示有多少個提交收到了slave的確認消息
Rpl_semi_sync_slave_status:1表示備庫上slave功能開啓而且運行正常,0表示功能爲開啓或者運行異常

經過mysql> SHOW STATUS LIKE 'Rpl_semi_sync%';查看各個參數的狀態

 

mysql並行複製

 

在MySQL 5.6版本以前,Slave服務器上有兩個線程I/O線程和SQL線程。I/O線程負責接收二進制日誌(更準確的說是二進制日誌的event),SQL線程進行回放二進制日誌。若是在MySQL 5.6版本開啓並行複製功能,那麼SQL線程就變爲了coordinator線程,coordinator線程主要負責之前兩部分的內容:

 

  • 若判斷能夠並行執行,那麼選擇worker線程執行事務的二進制日誌
  • 若判斷不能夠並行執行,如該操做是DDL,亦或者是事務跨schema操做,則等待全部的worker線程執行完成以後,再執行當前的日誌

 

這意味着 coordinator線程並非僅將日誌發送給worker線程,本身也能夠回放日誌,可是全部能夠並行的操做交付由worker線程完成

(疑問:這裏是在判斷不能夠並行執行時,在等待全部的worker線程執行完成後,是由coordinator執行仍是由worker進程非並行進行。從上面兩句話中看不出coordinator進程回放日誌。)

上述機制實現了基於schema的並行複製存在兩個問題,首先是crash safe功能很差作,由於可能以後執行的事務因爲並行複製的關係先完成執行,那麼當發生crash的時候,這部分的處理邏輯是比較複雜的。從代碼上看,5.6這裏引入了Low-Water-Mark標記來解決該問題,其是但願藉助於日誌的冪等性來解決該問題,不過5.6的二進制日誌回放還不能實現冪等性。另外一個最爲關鍵的問題是這樣設計的並行複製效果並不高,若是用戶實例僅有一個庫,那麼就沒法實現並行回放,甚至性能會比原來的單線程更差。而 單庫多表是比多庫多表更爲常見的一種情形 。

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

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

從MySQL官方來看,其並行複製的本來計劃是支持表級的並行複製和行級的並行複製,行級的並行複製經過解析ROW格式的二進制日誌的方式來完成, WL#4648 。可是最終出現給小夥伴的確是在開發計劃中稱爲:MTS: Prepared transactions slave parallel applier,可見: WL#6314 

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

並行複製配置與調優

master_info_repository

務必將參數master_info_repostitory設置爲TABLE,這樣性能能夠有50%~80%的提高。這是由於並行複製開啓後對於元master.info這個文件的更新將會大幅提高,資源的競爭也會變大。在以前 InnoSQL 的版本中,添加了參數來控制刷新master.info這個文件的頻率,甚至能夠不刷新這個文件。由於刷新這個文件是沒有必要的,即根據master-info.log這個文件恢復自己就是不可靠的。在MySQL 5.7中,Inside君推薦將master_info_repository設置爲TABLE,來減少這部分的開銷。

slave_parallel_workers

若將slave_parallel_workers設置爲0,則MySQL 5.7退化爲原單線程複製,但將slave_parallel_workers設置爲1,則SQL線程功能轉化爲coordinator線程,可是隻有1個worker線程進行回放,也是單線程複製。然而,這兩種性能卻又有一些的區別,由於多了一次coordinator線程的轉發,所以slave_parallel_workers=1的性能反而比0還要差

配置:

【從庫】

master_info_repository = TABLE
relay_log_info_repository = TABLE
relay_log_recovery = 1
slave-parallel-type = LOGICAL_CLOCK
slave-parallel-workers = 16
slave_preserve_commit_order=1
slave_transaction_retries=128

 

MySQL基於GTID的複製

GTID(global transaction identifiers)複製是徹底基於事務的複製,即每一個在主庫上執行的事務都會被分配一個惟一的全局ID並記錄和應用在從庫上這種複製方式簡化了創建slave和master/slave之間切換的工做,由於其徹底不須要找當前執行的bin log和log中的位置完成切換,一個GTID是master上執行的任何commit事務所分配的全局惟一ID標示,其由兩部分組成:GTID = source_id:transaction_id
Source_id表明主庫的server_uuid,transaction_id表明事務按順序提交的ID,好比第一個提交則是1,第十個提交的事務就是10,GTID集合表明一組GTID

GTID複製原理

① 當一個事務在主庫提交時,該事務就被賦予了一個GTID,並記錄在主庫的binary log
② 主庫的binary log會被傳輸到從庫的relay log中,從庫讀取此GTID並生成gtid_next系統參數
③ 從庫驗證此GTID並無在本身的binary log中使用,則應用此事務在從庫上

mysql5.7.4開始;gtid_executed系統表記錄同步複製的信息(UUID:事務號),這樣就能夠不用開啓log_slave_updates參數,減小了從庫的壓力

GTID複製【】
主從同樣都須要添加;同步記錄會存放在mysql系統庫的gtid_executed表中
gtid-mode=on
enforce-gtid-consistency=on
從庫【】
stop slave ;
reset slave all;
CHANGE MASTER TO
MASTER_HOST=‘master_host_name’, ##主庫的主機名
MASTER_PORT=port_number ##主庫的端口號
MASTER_USER=‘replication_user_name’, ##複製的數據庫用戶名
MASTER_PASSWORD=‘replication_password’, ##複製的用戶密碼
MASTER_AUTO_POSITION = 1;
主從複製過程當中參數詳解:
replicate-do-db :在從庫定義的
binlog-do-db:在主庫定義的,那些庫中的修改能夠記錄到二進制日誌中

使用GTID複製的限制條件:
因爲GTID複製是依賴於事務的,因此MySQL的一些屬性不支持,當一個事務中既包含對InnoDB表的操做,也包含對非事務型存儲引擎表(MyISAM)的操做時,就會致使一個事務中可能會產生多個GTID的狀況;或者是當master和slave的表使用的存儲引擎不同時,都會致使GTID複製功能不正常
create table…select語句在基於語句複製的環境中是不安全的,在基於行復制的環境中,此語句會被拆分紅兩個事件,一是建立表,二是insert數據,在某些狀況下這兩個事件會被分配相同的GTID,而致使insert數據的操做被忽略,因此GTID複製不支持create table … select語句create/drop temporary table語句在GTID複製環境中不能放在事務中執行,只能單獨執行,而且autocommit要開啓sql_slave_skip_counter語句是不支持的,若是想要跳過事務,可使用gtid_executed變量

基於GTID複製跳過錯誤實際應用:

1.stop slave;
2.set GTID_NEXT='f0e1cd81-46cc-11e8-87fb-00163e321fb5:5600010'; 注:GTID_NEXT=Executed_Gtid_Set 當前執行的事物+1
3.begin; commit; 執行一個空事物
4.SET @@SESSION.GTID_NEXT= 'AUTOMATIC';
5.start slave

 

參考:

https://www.cnblogs.com/xiaotengyi/p/5532191.html

相關文章
相關標籤/搜索