一、主從復制
1.)普通主從復制:
普通主從復制主要是基於二進制日志文件位置的復制,因此主必須啟動二進制日志記錄並建立唯一的服務器ID,復制組中的每個服務器都必須配置唯一的服務器ID。如果您省略server-id(或者明確地將其設置為其默認值0),則主設備將拒絕來自從設備的任何連接。
2.) GTID 主從:
(1.)基本概念
MySQL 5.6 的新特性之一,全局事務標識符(GTID)是創建的唯一標識符,並與在源(主)服務器上提交的每個事務相關聯。此標識符不但是唯一的,而且在給定復制設置中的所有服務器上都是唯一的。所有交易和所有GTID之間都有一對一的映射關系 。它由服務器ID以及事務ID組合而成。這個全局事務ID不僅僅在原始服務器上唯一,在所有存在主從關系 的mysql服務器上也是唯一的。正是因為這樣一個特性使得mysql的主從復制變得更加簡單,以及數據庫一致性更可靠。一個GTID在一個服務器上只執行一次,避免重復執行導致數據混亂或者主從不一致。
一個GTID被表示為一對坐標,用冒號(:)分隔,如下所示:GTID = source_id:transaction_id,source_id標識的源服務器。通常情況下,服務器 server_uuid用於這個目的。這transaction_id是一個序列號,由在此服務器上提交事務的順序決定 .
3E11FA47-71CA-11E1-9E33-C80AA9429562:23
在傳統的主從復制slave端,binlog是不用開啟的,但是在GTID中slave端的binlog是必須開啟的,目的是記錄執行過的GTID(強制)。GTID用來代替classic的復制方法,不在使用binlog+pos開啟復制。而是使用master_auto_postion=1的方式自動匹配GTID斷點進行復制。
mysql的主從復制是十分經典的一個應用,但是主從之間總會有數據一致性(data consistency )的問題,一般情況從庫會落后主庫幾個小時,而且在傳統一主多從(mysql5.6之前)的模型中當master down掉后,我們不只是需要將一個slave提成master就可以,還要將其他slave的同步目的地從以前的master改成現在master,而且bin-log的序號和偏移量也要去查看,這是十分不方便和耗時的,但mysql5.6引入gtid之后解決了這個問題。
紅色代表GTID,綠色代表傳統主從:

(2.)GTID的工作原理:
1、當一個事務在主庫端執行並提交時,產生GTID,一同記錄到binlog日志中。 2、binlog傳輸到slave,並存儲到slave的relaylog后,讀取這個GTID的這個值設置gtid_next變量,即告訴Slave,下一個要執行的GTID值。 3、sql線程從relay log中獲取GTID,然后對比slave端的binlog是否有該GTID。 4、如果有記錄,說明該GTID的事務已經執行,slave會忽略。 5、如果沒有記錄,slave就會執行該GTID事務,並記錄該GTID到自身的binlog, 在讀取執行事務前會先檢查其他session持有該GTID,確保不被重復執行。 6、在解析過程中會判斷是否有主鍵,如果有就用二級索引,如果沒有就用全部掃描。
二、GTID參數配置
1、主master:
[mysqld] #GTID: server_id=1 #服務器id gtid_mode=on #開啟gtid模式 log_slave_updates ## 表示即可以當從也可以當主 enforce_gtid_consistency=on #強制gtid一致性,開啟后對於特定create table不被支持 #binlog log_bin=master-binlog
#log-bin=/data/mysql/mysql-bin.log //binlog日志文件,(文件名如果是絕對路徑,必須指定索引文件)
#log_bin_index = /var/lib/mysql/mysql-bin.index //是binlog文件的索引文件,這個文件管理了所有的binlog文件的目錄
log-slave-updates=1
binlog_format=row #binlog日志格式,強烈建議,其他格式可能造成數據不一致
expire_logs_days=7 //binlog過期清理時間
#relay logskip_slave_start=1
2、從slave:
與主的配置沒有區別,僅僅只是server_id不一致。
三、配置主從
1.)master:
創建並授權salve遠程訪問的用戶:
GRANT REPLICATION SLAVE ON *.* TO root@192.168.50.28 IDENTIFIED BY '123456';
flush privileges;
查看授權slave用戶表:
show grants for user@localhost;
查看binlog信息:show master status;
2.)GTID—slave;(注意:GTID主從必須啟用MASTER_AUTO_POSITION而且不能跟bin與pos同時配置。)
CHANGE MASTER TO MASTER_HOST='192.168.50.116',MASTER_PORT=3306,MASTER_USER='root',MASTER_PASSWORD='123456',MASTER_AUTO_POSITION=1;
start slave;
show slave status\G;
#MASTER_AUTO_POSITION: (mysql5.6.5及其后續版本)進行change master to時使用MASTER_AUTO_POSITION = 1,slave連接master將使用基於
GTID的復制協議。等於0則恢復到老的文件復制協議。
3.)傳統復制—slave配置;(這里的bin與pos根據實際情況更換)
CHANGE MASTER TO MASTER_HOST='192.168.50.116',MASTER_PORT=3306,MASTER_USER='root',MASTER_PASSWORD='123456', master_log_file='mysql-bin.000003',master_log_pos=308;
start slave;
show slave status\G;
關鍵:在配置文件中啟用GTID的情況下,change語句才是決定啟用GTID還是傳統主從的關鍵。
進行主備切換的時候,一般都會先對主庫進行只讀操作(on),然后主備同步完成后,再把備庫置為可讀寫(off)。這樣可以避免切換的過程中雙寫引起臟數據。:set global read_only=on/off
四、特殊情況下,需要重置主從
stop slave;
reset slave all; #重置全部的從信息
reset master; #重置主
五、事物跳過(傳統與GTID的跳過方法不同)
1.傳統
set global sql_slave_skip_counter = 1;
#可以忽略N個事件(event),通常一個SQL是一個事件。
2.GTID跳過事務沖突
首先,我們需要先查看當前SLAVE復制的進度:SHOW SLAVE STATUS\G
Retrieved_Gtid_Set:aaa-bbb-ccc-ddd:N (表示收到的事務)
Executed_Gtid_Set:aaa-bbb-ccc-ddd:N (表示已經執行完的事務)
看Executed_Gtid_Set 到了31這個事務GTID位置,在這下一個位置(32)上發生錯誤。這時候,我們需要手工調整SLAVE已清除的GTID列表 GTID_PURGED,人為通知SLAVE哪些事務已經被清除了,后續可以忽略:
STOP SLAVE; RESET MASTER; SET @@GLOBAL.GTID_PURGED = “3a16ef7a-75f5-11e4-8960-deadeb54b599:1-283,f2b6c829-9c87-11e4-84e8-deadeb54b599:1-32”; START SLAVE;
上面這些命令的用意是,忽略 f2b6c829-9c87-11e4-84e8-deadeb54b599:32 這個GTID事務,下一次事務接着從 33 這個GTID開始,即可跳過上述錯誤。
從服務器上負責同步的有二類線程: 1) IO thread 2) SQL thread
Slave_IO_Running:從服務器正從主服務器上讀取BINLOG日志,並寫入從服務器的中繼日志.
Slave_SQL_Running:進程正在讀取從服務器的BINLOG中繼日志,並轉化為SQL執行
IO thread 決定了Retrieved_Gtid_Set
SQL thread 決定了Executed_Gtid_Set
IO thread負責獲取master上的binary log, 然后多個sql threads負責執行。由於IO thread先於SQL thread,Retrieved_Gtid_Set可能會略多於Executed_Gtid_Set。比如: SHOW slave STATUS \G
....... ....... Retrieved_Gtid_Set: 67cd9435-7cae-11e2-aa8d-00241db92e69:1-9 Executed_Gtid_Set: 67cd9435-7cae-11e2-aa8d-00241db92e69:1-7 Auto_Position: 1
1.)注入空事務:
stop slave; SET GTID_NEXT='aaa-bbb-ccc-ddd:N'; #要想跳過錯誤的GTID或則是想要跳過的GTID,就需要指定下一個事物的執行版本 BEGIN; COMMIT; #注入一個空事務 SET GTID_NEXT='AUTOMATIC'; #自動尋找GTID事務 一旦所有事務標識符以這種方式使用空事務恢復后,您必須刷新並清除從屬服務器的二進制日志,如下所示,其中 N是當前二進制日志文件名稱 的非零后綴;或者reset slave; FLUSH LOGS; PURGE BINARY LOGS TO 'master-bin.00000N'; start slave;
2.)重置master方法跳過錯誤
mysql> STOP SLAVE;
mysql> RESET MASTER;
mysql> SET @@GLOBAL.GTID_PURGED ='8f9e146f-0a18-11e7-810a-0050568833c8:1-4'
mysql> START SLAVE;
注意:在GTID主從的建立初期,slave的數據一定要是從master mysqldump過去的並且更加--all-databases參數。否則手動補齊的數據會出現slave_sql_running為NO的情況,這是因為主的操作記錄會保存在GTID與binlog中,然后slave會同步主的GTID與binlog並進行相應的操作,這時兩邊的數據雖然是一致的,但是同步過來master的GTID中包含了主做過的一些sql操作,而此時slave的環境不滿足sql語句的執行就會沖突。解決辦法是:1.)不斷的執行跳過事務的操作直到沒有報錯。2.)刷新master的GTID“reset master”然后重新再slave執行change同步。
六、報錯案例:
1.)
2017-10-12T09:59:27.660287Z 4 [ERROR] Slave I/O for channel '': Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs; these UUIDs must be different for replication to work. Error_code: 1593
解決方法:
如果是copy的data目錄可能會出現這個錯,將data目錄里auto.cnf 文件中的uuid改為與master不一樣的即可。
2.)傳統主從
2017-10-12T10:09:15.365312Z 4 [ERROR] Slave I/O for channel '': Got fatal error 1236 from master when reading data from binary log: 'Could not find first log file name in binary log index file', Error_code: 1236
解決辦法:
是因為找不到master的二進制文件,查看master的binlog二進制文件、pos位置是否與slave相同,不相同關閉salve並在slave執行CHANGE MASTER TO MASTER_LOG_FILE='mysqld-bin.000011',MASTER_LOG_POS=106;更改,然后開啟start slave;並進行查看show slave status\G
3.) GTID主從
Got fatal error 1236 from master when reading data from binary log: 'The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has purged binary logs containing GTIDs that the slave requires.'
解決辦法:忽略purged的部分,強行同步
master確認已經purge的部分:show global variables like '%gtid%';
stop slave,在slave上通過set global gtid_purged='xxxx'的方式,跳過已經purge的部分
4.)
主從不同步,但slave顯示雙yes,日志無報錯問題。
這個解決方法是下下策,我不知道不同步的原因是什么,如果有知道的T友,請評論告知。
重置主從:reset master reset slave
備份主的全庫到slave:
mysqldump -h 192.168.50.116 -uroot -p123456 --all-databases --skip-lock-tables --set-gtid-purged=off > qk.sql
然后從導入:mysql -uroot -p123456 <aaa.sql
導入時若提示:ERROR 1840 (HY000) at line 24: @@GLOBAL.GTID_PURGED can only be set when @@GLOBAL.GTID_EXECUTED is empty.則在本地執行reset master即可。導入成功后重新開啟slave同步,如若slave需要重新掛載在master端,則執行命令change時忽略MASTER_AUTO_POSITION即可。
注意:
開啟主從復制之后,就不可以在從的上面進行操作,否則會出現slave_sql_running為NO的提示。
當已經在從庫進行刪除或則添加數據時,挽救的方法就是關閉slave,然后將刪除的數據創建回來或將添加的數據刪除,目的是為了與master一致,然后開啟slave。最好是將從庫設置為只讀模式,但是無法對super的用戶起效。
5.)
Got fatal error 1236 from master when reading data from binary log: 'The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has purged binary logs containing GTIDs that the slave requires.'
解決辦法:
這類報錯往往是因為master清除了相關的GTID事務導致無法同步的。通常是因為從庫因為某些原因需要重新接受master的GTID事務,比如像slave導入備份重新指向master。這時就需要在master執行:show global variables like '%gtid%'; 找出被purged的條目,然后再slave執行本文中 “GTID跳過事務沖突”的步驟即可。
優秀文章分享:
http://www.cnblogs.com/luckcs/articles/6295992.html
http://blog.csdn.net/leshami/article/details/50630691
