GTID定義:
定義: | GTID即全局事務ID(global transaction identifier),一個事物對應一個GTID |
引入: | MySQL-5.6.5開始支援,MySQL-5.6.10後開始完善 |
組成: | GTID = server_uuid :transaction_id |
server_uuid | 首次啟動時 MySQL 會自動生成一個 server_uuid,并且儲存到 auto.cnf 檔案,一個執行個體對應一個server_uuid |
transaction_id | 從 1 開始的自增計數,表示在這個主庫上執行的第 n 個事務 |
開啟GTID:
[mysqld] 配置 | |
#GTID | |
gtid_mode=on | 開啟GTID |
enforce-gtid-consistency = on | 啟用強一緻性檢查,避免create table...select操作 |
log-slave-updates=1 | 允許下端接入slave |
#binlog | |
log-bin=mysql-bin | 開啟binlog |
binlog_format=row | binlog格式為row模式 |
GTID優缺點:優點:
- slave在做同步複制時,無須找到binlog日志和POS點,直接change master to master_auto_position=1即可,自動找點同步;
- 搭建主從複制簡單。
缺點:
- GTID同步複制是基于事務。是以Myisam表不支援,這可能導緻多個GTID配置設定給同一個事務;
- CREATE TABLE ...SELECT語句不支援。因為該語句會被拆分成createtable 和insert兩個事務,并且這個兩個事務被配置設定了同一個GTID,這會導緻insert被備庫忽略掉;
- 不支援CREATE TEMPORARY TABLE、DROP TEMPORARYTABLE 臨時表操作;
- Errant transaction問題:即從庫不能進行任何事物型操作,會引入新的GTID,當binlog被清除後,再進行主從切換,會導緻其他從庫找不到此GTID,進而挂載不上。
GTID原理:GTID的最大特性就是它的Failover能力,如下架構,當主庫A cresh時,需要進行主從切換,将B或C其中一台提升為主,傳統模式我們無法确認哪台資料較新,由于同一個事務在每台機器上所在的binlog名字和位置都不一樣,那麼怎麼找到C目前同步停止點,對應B的master_log_file和master_log_pos,需要通過程式對比或者借助MHA等工具。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5yMxQzN3QGZyUjMjZDOxMWMjVmZhVTOhRWYzQDO5gzMz8CXxAzLcNDMxIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLzM3Lc9CX6MHc0RHaiojIsJye.png)
GTID出現後,這個問題就顯得非常簡單。由于同一事務的GTID在所有節點上的值一緻,那麼根據
C
目前停止點的GTID就能唯一定位到
B
上的GTID。甚至由于
MASTER_AUTO_POSITION
功能的出現,我們都不需要知道GTID的具體值,直接使用
CHANGE MASTER TO MASTER_HOST='xxx', MASTER_AUTO_POSITION=1
指令就可以直接完成failover的工作。
GTID主要參數說明:
show global variables like '%gtid%';
gtid_next | session級别,指定下一個GTID擷取的方式,預設AUTOMATIC | 使用下一個自動産生的GTID,slave解析binlog,将GTID賦給gtid_next并于下一個事務使用此GTID; |
gtid_executed | 執行個體已執行的所有GTID集合 | slave使用GTID前先做檢查,確定其沒被使用過;reset master會将其重置為空; |
gtid_owned | 隻讀變量,分别描述session和global目前擁有的gtid集合 | 確定沒有被其他session正在使用,多個用戶端不可并發運作同一個事務; |
gtid_purged | 已清除的binlog中包含的GTID集合 | 伺服器啟動時,讀取最舊binlog的previous_gtid_log_event并将其指派;每purge一個binlog,則重置一次;reset master會将其重置為空 |
GTID複制錯誤修複:
一、手動跳過錯誤事物(在從庫上)
- STOP SLAVE;
- RESET MASTER;
- SET @@GLOBAL.GTID_PURGED = 'f2b6c829-9c87-11e4-84e8-deadeb54b599:1-32';
- START SLAVE;
上面這些指令的用意是,忽略 f2b6c829-9c87-11e4-84e8-deadeb54b599:32 這個GTID事務,下一次事務接着從 33 這個GTID開始,即可跳過上述錯誤。注:無論是否開啟了GTID,都可以使用percona 的 pt-slave-restart工具去跳過錯誤。
二、Errant transaction問題修複:
此問題主要是采用GTID複制的情況下,在slave上進行了事物操作,此時這台slave就多出來一個或多個其他slave節點和master節點沒有的事務。我們知道Binlog預設保留7天,7天後這些事物産生的binlog會被删除,當發生failover的時,這個slave被提升為主,由于其他從庫已經找不到新主庫事物所産生的binlog,此時其他從庫會挂載不上,造成資料庫單點,十分危險。
步驟 | 主 | 從 |
1 | create table t1(id int);從庫執行一個事物 | |
2 | show global variables like '%gtid%'; | gtid_executed |984f9b33-2118-11e8-b4d2-8a5337dcf960:1-6 | | | gtid_executed | 9831a0f8-2118-11e8-b585-96f5258290c0:1, 984f9b33-2118-11e8-b4d2-8a5337dcf960:1-6 此時從庫已經多了一個GTID |
3 | stop slave; | |
4 | reset master; | |
5 | set @@GLOBAL.GTID_PURGED = '984f9b33-2118-11e8-b4d2-8a5337dcf960:1-6'; | |
6 | start slave; | |
7 | 此時gtid_executed已經和主庫一緻 |
- 傳統解決方案:通過在主庫手動設定下一次事物GTID,執行一條空事物,實作跟從庫一緻
show global variables like '%gtid%';| gtid_executed |984f9b33-2118-11e8-b4d2-8a5337dcf960:1-6 | | show global variables like '%gtid%';| gtid_executed | 9831a0f8-2118-11e8-b585-96f5258290c0:1,984f9b33-2118-11e8-b4d2-8a5337dcf960:1-6此時從庫已經多了一個GTID | |
set gtid_next='9831a0f8-2118-11e8-b585-96f5258290c0:1';在session級别,指定此GTID給下一個事物 | ||
begin; | ||
commit; | ||
set gtid_next='automatic'; | ||
show global variables like '%gtid%';| gtid_executed | 9831a0f8-2118-11e8-b585-96f5258290c0:1,984f9b33-2118-11e8-b4d2-8a5337dcf960:1-6此時跟從庫已經一緻 |
- 通過類似一種“欺騙”方(優先選擇此方式,無需操作主庫)
- mysqlslavetrx優雅處理方式