1、主從復制概述
MySQL主從復制也可以稱為MySQL主從同步,它是構建數據庫高可用集群架構的基礎。它通過將一台主機的數據復制到其他一台或多台主機上,並重新應用relay log中的SQL語句來實現復制功能。MySQL支持單向、雙向、鏈式級聯、異步復制,5.5版本之后加入的半同步復制,5.6版本之后的GTID復制,MySQL5.7的多源復制、並行復制、loss-less復制。
1.1 常見的幾種主從架構
1)單向主從模式:Master ——> Slave
2)雙向主從模式:Master <====> Master
3)級聯主從模式:Master ——> Slave1 ——> Slave2
4)一主多從模式
5)多主一從模式
1.2 主從復制功能
1)實時災備
2)讀寫分離
3)高可用
4)從庫數據統計
5)從庫數據備份
6)平滑升級
1.3 主從復制原理
主從同步過程中主服務器有一個工作線程I/O dump thread,從服務器有兩個工作線程I/O thread和SQL thread。
主庫把外界接收的SQL請求記錄到自己的binlog日志中,從庫的I/O thread去請求主庫的binlog日志,並將binlog日志寫到中繼日志中,然后從庫重做中繼日志的SQL語句。主庫通過I/O dump thread給從庫I/O thread傳送binlog日志。
原理圖
2、復制原理
2.1 異步復制
異步復制是MySQL默認的復制方式,主庫寫入binlog日志后即可成功返回客戶端,無須等待binlog日志傳遞給從庫的過程,但是一旦主庫宕機,就有可能出現丟失數據的情況。
2.2 半同步復制
MySQL默認的復制方式是異步復制,但是當主庫宕機,在高可用架構坐准備切換,就會造成新的主庫丟失數據的現象。
MySQL5.5版本之后引入了半同步復制,但是主從服務器必須同時安裝半同步復制插件。在該功能下,確保從庫接收完成主庫傳遞過來的binlog內容已經寫入到自己的relay log后才會通知主庫上面的等待線程。如果等待超時(超時參數:rpl_semi_sync_master_timeout),則關閉半同步復制,並自動轉換為異步復制模式,直到至少有一台從庫通知主庫已經接收到binlog信息為止。
半同步復制原理圖:
半同步復制提升了主從之間數據的一致性,讓復制更加安全可靠,在5.7 版本中又增加了rpl_semi_sync_master_wait_point參數,用來控制半同步模式下主庫返回給session事務成功之前的事務提交方式。
該參數有兩個值:
1)AFTER_COMMIT:5.6版本的默認值,主庫將每個事務寫入binlog,並傳遞給從庫,刷新到中繼日志中,同時主庫提交事務。之后主庫開始等待從庫的反饋,只有收到從庫的回復之后,master才將commit OK的結果反饋給客戶端。
2)AFTER_SYNC:5.7版本新增,也是默認的半同步復制方式。主庫將每個事務寫入binlog並傳遞給從庫,刷新到中繼日志中,主庫開始等待從庫的反饋,接收到從庫的回復之后,再提交事務並且返回commit OK結果給客戶端。
注意:可以通過rpl_semi_sync_master_wait_for_slave_count參數來控制主庫接收多少個從庫寫事務成功反饋,才返回成功給客戶端。生產環境中使用半同步復制方式,當從庫出現故障,等待超時的時間又很長,導致主庫無法接收從庫信息而無法正常寫入時,可通過該參數剔除故障從庫。另外rpl_semi_sync_master_timeout單位是毫秒,它表示如果主庫等待從庫回復消息的時間超過該值,就自動切換為異步復制模式,建議調整為很大,禁止向異步復制切換來保證數據復制的安全性。MySQL 5.7默認的半同步復制方式是after_sync模式。
在AFTER_SYNC模式下,即使主庫宕機,所有在主庫上已經提交的事務都能保證已經同步到從庫的中繼日志中,不會丟任何數據。
2.3 GTID復制
GTID又叫全局事務ID,是一個以提交事務的編號,並且是一個全局唯一的編號。GTID是由server_uuid和事務id組成的,即GTID=server_uuid:transaction_id。
server_uuid是數據庫啟動自動生成的,保存在auto.cnf文件下,transaction_id是事務提交時由系統順序分配的一個不會重復的序列行。
GTID存在的價值:
1)GTID使用master_auto_position=1代替了基於binlog和position號的主從復制方式,更便於主從復制的搭建。
2)GTID可以知道事務在最開始是哪個實例上提交的。
3)GTID方便實現主從之間的failover,無須找position和binlog。
GTID限制條件:
1)不能使用create table table_name select * from table_name。
2)不支持CREATE TEMPORARY TABLE or DROP TEMPORARY TABLE語句操作。
3)不支持sql_slave_skip_counter。