MySQL-5.6版本GTID的主從複製

mysql GTID Replicationmysql

1、GTID的概述:git

一、全局事物標識:global transaction identifieds。sql

二、GTID事物是全局惟一性的,且一個事務對應一個GTID。數據庫

三、一個GTID在一個服務器上只執行一次,避免重複執行致使數據混亂或者主從不一致。安全

四、GTID用來代替classic的複製方法,不在使用binlog+pos開啓複製。而是使用master_auto_postion=1的方式自動匹配GTID斷點進行復制。服務器

五、MySQL-5.6.5開始支持的,MySQL-5.6.10後開始完善。session

六、在傳統的slave端,binlog是不用開啓的,可是在GTID中,slave端的binlog是必須開啓的,目的是記錄執行過的GTID(強制)。多線程

 

2、GTID的組成部分:ide

前面是server_uuid:後面是一個序列號post

例如:server_uuid:sequence number

7800a22c-95ae-11e4-983d-080027de205a:10

UUID:每一個mysql實例的惟一ID,因爲會傳遞到slave,因此也能夠理解爲源ID。

Sequence number:在每臺MySQL服務器上都是從1開始自增加的序列,一個數值對應一個事務。

 

3、GTID比傳統複製的優點:

一、更簡單的實現failover,不用之前那樣在須要找log_file和log_Pos。

二、更簡單的搭建主從複製。

三、比傳統複製更加安全。

四、GTID是連續沒有空洞的,所以主從庫出現數據衝突時,能夠用添加空事物的方式進行跳過。

 

4、GTID的工做原理:

一、master更新數據時,會在事務前產生GTID,一同記錄到binlog日誌中。

二、slave端的i/o 線程將變動的binlog,寫入到本地的relay log中。

三、sql線程從relay log中獲取GTID,而後對比slave端的binlog是否有記錄。

四、若是有記錄,說明該GTID的事務已經執行,slave會忽略。

五、若是沒有記錄,slave就會從relay log中執行該GTID的事務,並記錄到binlog。

六、在解析過程當中會判斷是否有主鍵,若是沒有就用二級索引,若是沒有就用所有掃描。

要點:

一、slave在接受master的binlog時,會校驗master的GTID是否已經執行過(一個服務器只能執行一次)。

二、爲了保證主從數據的一致性,多線程只能同時執行一個GTID。

 

6、使用GTID搭建mysql的主從複製的主要參數:

[mysqld]

#GTID:

gtid_mode=on

enforce_gtid_consistency=on

server_id=2003306    #天天實例的server_id都要不同

 

#binlog

log-bin=mysqlbin

log-slave-updates=1   #容許下端接入slave

binlog_format=row      #強烈建議,其餘格式可能形成數據不一致

 

#relay log

skip_slave_start=1

注意:建議使用mysql-5.6.5以上的最新版本。

 

(二)、啓動GTID的兩種方法:

方法1、

一、若是是在已經跑的服務器,你須要重啓一下mysql server。

二、啓動以前,必定要先關閉master的寫入,保證全部slave端都已經和master端數據保持同步。

三、全部slave須要加上skip_slave_start=1的配置參數,避免啓動後仍是使用老的複製協議。

方法2、

一、若是是新搭建的服務器,直接啓動就好了。

7、master-slave搭建的注意事項:

(一)、使用GTID的方式,把salve端掛載master端:

一、啓動之後最好不要當即執行事務,而是先change master上。

二、而後在執行事務,固然知不是必須的。

三、使用下面的sql切換slave到新的master。

stop slave;

change master to

master_host = 192.168.100.200,

master_port = 3306,

master_user = abobo,

master_password=123,

master_auto_position = 1;

 

(二)、若是給已經運行的GTID的master端添加一個新的slave

 有兩種方法:

方法1、適用於master也是新建不久的狀況。

一、若是你的master全部的binlog還在。能夠選擇相似於上面的方法,安裝slave,直接change master to到master端。

二、原理是直接獲取master全部的GTID並執行。

三、優勢:簡單方便。

四、缺點:若是binlog太多,數據徹底同步須要時間較長,而且master一開始就啓用了GTUD。

 

方法2、適用於擁有較大數據的狀況。(推薦)

一、經過master或者其餘slave的備份搭建新的slave。(看第三部分)

二、原理:獲取master的數據和這些數據對應的GTID範圍,而後經過slave設置@@global.gtid_purged跳過備份包含的gtid。

三、優勢:是能夠避免第一種方法的不足。

四、缺點:相對來講有點複雜。

(三)、經過備份搭建新的slave:(方法二的擴展)

兩種方法:

方法1、mysqldump的方式:

一、在備份的時候指定--master-data=2(來保存binlog的文件號和位置的命令)。

二、使用mysqldump的命令在dump文件裏能夠看到下面兩個信息:

SET @@SESSION.SQL_LOG_BIN=0;

SET @@GLOBAL.GTID_PURGED='7800a22c-95ae-11e4-983d-080027de205a:1-8';

三、將備份還原到slave後,使用change master to命令掛載master端。

注意:在mysql5.6.9之後的命令才支持這個功能。

 

方法2、percona Xtrabackup

一、Xtrabackup_binlog_info文件中,包含global.gtid_purged='XXXXXX:XXXX'的信息。

二、而後到slave去手工的 SET GLOBAL.GTID_PURGED='XXXXXX:XXXX'。

三、恢復備份,開啓change master to 命令。

注意:若是系統運行了好久,沒法找到GTID的變好了,能夠經過上面的方式進行查找。

8、GTID如何跳過事務衝突:

一、這個功能主要跳過事務,代替原來的set global sql_slave_skip_counter = 1。

二、因爲在這個GTID必須是連續的,正常狀況同一個服務器產生的GTID是不會存在空缺的。因此不能簡單的skip掉一個事務,只能經過注入空事物的方法替換掉一個實際操做事務。

三、注入空事物的方法:

stop slave;

set gtid_next='xxxxxxx:N';

begin;commit;

set gtid_next='AUTOMAIC';

start slave;

四、這裏的xxxxx:N 也就是你的slave sql thread報錯的GTID,或者說是你想要跳過的GTID。

 

9、GTID的參數註釋:

[master]>show global variables like '%gtid%';

一、enforce_gtid_consistency:開啓gtid的一些安全限制(介意開啓)。

二、gtid_executed:全局和seeeion級別均可以用。用來保存已經執行過的GTIDs。

貼士:show  master status\G;輸出結果中的Executed_Gtid_Set和gitd_executed一致。reset master時,此值會被清空。

三、gtid_owned:全局和session級別均可用,全局表示全部服務器擁有GTIDs,session級別表示當前client擁有全部GTIDs。(此功能用的少)

四、gtid_mode:是否開啓GTID功能。

五、gtid_purged:全局參數,設置在binlog中,已經purged的GTIDs,而且purged掉的GTIDs會包含到gtid_executed中。

貼士:從而致使slave不會再去master請求這些GTIDs,而且Executed_Gtid_Set爲空時,才能夠設置此值。

 

六、gtid_next:這個時session級別的參數:

[master]>show session variables like '%gtid_next%';

 

10、關於GTID的一些功能限制:

(一)、更新非事務引擎:

一、Case重現:

master:對一個innodb表作一個多sql更新的事物,效果是產生一個GTID。

slave:對應的表是MYISAM引擎,執行這個GTID的第一個語句後就會報錯,由於非事務引擎一個sql就是一個事務。

 

二、錯誤編號:

last_Errno:1756

三、異常恢復方案:

(1)、簡單的stop slave; start slave;就可以忽略錯誤。可是這個時候主從的一致性已經出現問題。須要手工的把slave差的數據補上。

(2)、首先將引擎調整爲同樣的,slave也改成事務引擎。

 

(二)、create table ....select statements

一、case重現:

 master:直接執行一個create table select * from table;的sql

二、報錯:

error 1786

三、原理:

因爲create table ...select語句會生成兩個sql,一個是DDL建立表SQL,一個是insert into 插入數據的sql。因爲DDL會致使自動提交,因此這個sql至少須要兩個GTID,可是GTID模式下,只能給這個sql生成一個GTID,若是強制執行會致使和上面更新非事務引擎同樣的結果。

(三)、一個sql同事操做innodb引擎和myisam引擎:

case重現:t1表是innodb,t2表是myisam

一、update t1,t2 set t1.id=1000,t2.id=1000 where t1.id=t2.id;

二、報錯:1785

三、原理和第二個相同。

(四)、在一個replication grouop 中,全部的mysql必需要統一開啓或者關閉GTID功能。

一、case重現:

將一個未開啓gtid的slave經過原始的binlog和pos方式鏈接到開啓GTID的master。

 

二、報錯:

The slave IO thread stops because the master has @@GLOBAL.GTID_MODE ON and this server has @@GLOBAL.GTID_MODE OFF。

(五)、在一個replication group中,若是開啓GTID之後,就再也不容許使用classic的複製方式:

一、case重現:

將一個開啓gtid的slave經過原始的binlog和pos方式鏈接到開啓GTID的master。

二、報錯:

ERROR 1776(HY000):Parameters MASTER_LOG_FILE,MASTER_LOG_POS,RELAY_LOG_FILE and RELAY_LOG_POS cannot be set when MASTER_AUTO_POSITION is active。

 

(六)、GTID_MODE是not online的:

須要重啓才能生效,官方暫時不支持平滑的從classic replication切換到GTID replication。

貼士:

因爲GTID開啓須要重啓系統,一個複製組中全部的實例必須統一開啓或者關閉GTID,開啓GTID之後不能在使用classic複製。

問題:

也就是說在線業務必須統一關閉,而後再啓動,會致使服務中斷。

解決方案:

一、針對這種狀況,社區有兩種對應的平滑升級的方案:

一種是booking.com出品,這兩個差異在淘寶9月份數據庫月報裏有說明,加了一個橋接的服務器,既能夠運行GTID模式下,也能夠運行classic模式下。

另一種是facebook.com出品。全部的slave能夠在開啓GTID模式的狀況下,能夠鏈接到沒有開啓GTID模式的master。

 

二、能夠關閉一個部分,中止寫操做,可是讀不用,將另外一部分改爲GTID模式。

(七)、Temporary tables。

一、create temporary table和drop temporary table語句同樣在GTID環境下不支持。

若是--enforce_gtid_consistency參數開啓,而且autocommit=1,那麼可使用。

 

(八)、關於Errant transaction

一、Errant transaction:所謂的errant transaction也就是沒有規範的從master執行,而是直接從slave執行的事務。

二、因爲GTID協議的緣由,最開始已經提過(參見GTID architecture)。

三、若是slave有errant transaction產生,因爲GTID協議中的規則,很容易致使failover失敗。主要有兩種狀況:

 

a、在slave上作了無用的或者臨時的errant transaction操做,若是該slave升級成爲master的話,鏈接到它的全部數據庫都會獲取到這個事務。若是同樣就會產生衝突。

 

b、因爲作了這個errant transaction這個事務之後,其餘的slave尚未獲取這個errant transaction的GTID,須要從master上發同步給其餘的slave,可是主的binlog又被刪掉了,這時將會報錯。

 

四、總之:儘可能避免產生errant transaction。能夠經過:set sql_log_bin=off的方式在slave執行sql,可是也要考慮到數據一致性。

相關文章
相關標籤/搜索