一、GTID【Global Transaction Identifiers】
- GTID(Global Transaction Identifiers)是全局事務標識,GTID=server_uuid+transaction_id
- server_uuid,由於GTID會傳遞到slave,一個GTID在一個服務器上只執行一次
- transaction_id,為當前服務器上已提交事務的一個序列號,通常從1開始自增長的序列,一個數值對應一個事務。
- transaction_id 並不能代表執行順序
- GTID采用MASTER_AUTO_POSTION=1代替傳統復制(file+pos)
- GTID中slave端的binlog是必須開啟的,目的是記錄執行過的GTID(Executed_Gtid_Set)。
- GTID中包涵了server_uuid,方便了replication 的failove
二、GTID限制
1. 不支持非事務引擎
- 對於GTID不支持非事務引擎如何理解:
- 不支持非事務引擎不是不能建立myisam表、對myisam表DML
- innodb中一個事務中可以是多條SQL
- myisam中,一條DML生成一個GTID號,所以不支持事務
mysql> insert into user_myisam values (3,100); -- myisam每條sql自動提交,所以myisam中不存在事務的概念Executed_Gtid_Set: 59fe7a3e-9dd6-11e7-9d6c-000c29e57c69:1-68
2. 不支持create table …
s
elect 語句復制(主庫直接報錯)
mysql> create table t1 select * from user_innodb;ERROR 1786 (HY000): CREATE TABLE ... SELECT is forbidden when @@GLOBAL.ENFORCE_GTID_CONSISTENCY = 1.
3. 不允許在一個 S QL同時更新一個事務引擎和非事務引擎的表
mysql> begin;mysql> update user_innodb set money=100 where id=1;mysql> update user_myisam set money=100 where id=1;ERROR 1785 (HY000): When @@GLOBAL.ENFORCE_GTID_CONSISTENCY = 1, updates to non-transactional tables can only be done in either autocommitted statements or single-statement transactions, and never in the same statement as updates to transactional tables.
4. 在一個復制組中,必須要求統一開啟GTID或是關閉GTID
The slave IO thread stops because the master has @@GLOBAL.GTID_MODE ON and this server has @@GLOBAL.GTID_MODE OFF。
5. 對於create temporary table 和drop temporary table語句不支持
6. 不支持 s ql_ s lave_ s kip_count er
6. 不支持 s ql_ s lave_ s kip_count er
三、GTID主從復制
2.1 GTID的工作原理
- 當一個事務在主庫端執行並提交時,產生GTID,一同記錄到binlog日志中 [SET @@SESSION.GTID_NEXT]。
- binlog傳輸到slave,並存儲到slave的relaylog后,開始重做。
- 執行SET @@SESSION.GTID_NEXT,從庫對比[Executed_Gtid_Set] 是否執行過。
- 如果有記錄,說明該GTID的事務已經執行,slave會忽略;
- 如果沒有記錄,
- 在讀取執行事務前會先檢查其他session持有該GTID,確保不被重復執行。
- slave就會執行該GTID事務,並記錄[Executed_Gtid_Set],
2.2 啟動GTID的關鍵步驟
由最初的GTID復制拓撲(包括一個主站和一個從站)構成的啟動過程中的關鍵步驟如下:
- 如果復制已經在運行,則通過使這兩個服務器成為只讀方式來同步.
- mysql> SET @@global.read_only = ON;
- 停止兩個服務器。
- shell> mysqladmin -uusername -p shutdown;
- 重新啟動啟用GTID的兩個服務器,並配置正確的選項。
- gtid_mode=ON
- enforce-gtid-consistency=true
- 指示從機使用主機作為復制數據源,並使用自動定位,然后啟動從機。
- mysql> CHANGE MASTER TO> MASTER_HOST = host, MASTER_PORT = port, MASTER_USER = user, MASTER_PASSWORD = password, MASTER_AUTO_POSITION = 1;
- mysql> START SLAVE;
- 在兩台服務器上再次啟用讀取模式,以便它們可以接受更新。
- mysql> SET @@global.read_only = OFF;
2.3 數據和binlog的復制
1、數據的復制
- 使用mysql客戶端導入使用mysqldump創建的轉儲文件。
- 在源服務器上使用的 --master-data 選項包括二進制日志信息,
- 並 --set-gtid-purged 以AUTO(默認),或者 ON,包括有關在轉儲執行交易的信息。
2、binlog的復制
2.4 GTID相關的參數
1. --enforce-gtid-consistency
服務器通過允許執行只能使用GTID安全地記錄的語句來強制執行GTID一致性,影響:
CREATE TABLE ... SELECT 聲明
CREATE TEMPORARY TABLE或 DROP TEMPORARY TABLE交易中的語句
更新事務性和非事務性表的事務或語句。
2.
--gtid-mode
在MySQL 5.7.6及更高版本中,該 gtid_mode變量是動態的,並允許基於GTID的復制在線配置。
3. --gtid-executed-compression-period
該變量的默認值為1000; 這意味着,默認情況下,在每1000個事務之后執行表mysql.gtid_executed的壓縮。
4. binlog_gtid_simple_recovery
5.7.7 之后默認值為on,只從最新的最老的binlogflie中計算得到gtid_purged and gtid_executed的值。
2.5、GTID相關變量
1. gtid_executed
存儲已經執行過,並且記錄到 binlog 的全局事務 ID 集合。它對應的 MySQL variable 是 gtid_executed,可以用命令:
2. gtid_purgedlogged_gtids 用來判斷 MySQL 有沒有執行某個事務。例如,在 Master 發送 binlog 時,MySQL 5.6 能夠根據 Slave 提供的 logged_gtids 記錄,自動過濾 binlog 中不需要執行的事務
3. gtid_owned記錄從 binlog 刪除的全局事務 ID 集合。它對應的 MySQL Global variable 是:gtid_purged 。每當 MySQL 5.6 調用 purge_logs 刪除 binlog 時,會順帶更新 gtid_purged 的內容。這是通過讀剩下的 binlog 文件實現的
4. gtid_next正在由線程執行的全局事務 ID 集合。它對應的 MySQL variable 是:gtid_owned
- 取值:
- AUTOMATIC: Use the next automatically-generated global transaction ID.
- ANONYMOUS: Transactions do not have global identifiers, and are identified by file and position only.
- A global transaction ID in UUID:NUMBER format.
- Setting this variable has no effect if gtid_mode is OFF.
- After this variable has been set to UUID:NUMBER,當發生一個事務設置為commit或rollback,需要再次聲明這個變量的值。
四、GTID跳過單個、批量事務
1、概述
使用gtid跳過事務有兩種方法:
1. set gtid_next,可以跳過單個事務
2. set GTID_PURGED,可以跳過多個事務
2、跳過單個事物
1、情景:
主新建了test.t1 表,從誤操作刪掉了test.t1;
主往test.t1中插入一條數據,從庫報錯
從庫報錯內容:
mysql> show slave status \GLast_SQL_Error: Worker 3 failed executing transaction '59fe7a3e-9dd6-11e7-9d6c-000c29e57c69:17' at master log mysql-bin.000002, end_log_pos 3255; Error executing row event: 'Table 'test.t1' doesn't existRetrieved_Gtid_Set: 59fe7a3e-9dd6-11e7-9d6c-000c29e57c69:1-17Executed_Gtid_Set: 59fe7a3e-9dd6-11e7-9d6c-000c29e57c69:1-16,29bd8c99-9e4d-11e7-a072-000c29d00b2d:1,Auto_Position: 1
得知:
從庫在執行59fe7a3e-9dd6-11e7-9d6c-000c29e57c69:17 這個事務時,因為從庫沒有這個表而報錯了。
2、解決步驟:
root用戶手動重建test.t1表
主庫備份# mysqldump -uroot -p123123 -h127.0.0.1 --single-transaction --set-gtid-purged=off --triggers --routines --events test t1 >/tmp/t1.sql從庫恢復# cat t1.sql |mysql -uroot -p123123 test
root用戶手動在59fe7a3e-9dd6-11e7-9d6c-000c29e57c69:17 這個事務上執行一個空事務
> stop slave;> SET @@SESSION.GTID_NEXT= '59fe7a3e-9dd6-11e7-9d6c-000c29e57c69:17'/*!*/;> show variables like '%gtid%_next';> BEGIN;COMMIT;> SET gtid_next = 'AUTOMATIC';> START SLAVE;
3、批量跳過
1. 情景模擬
由於數據不一致嚴重,跳過單個事務不能繼續正常復制。
從庫刪掉單表,然后跳過批量sql,繼續復制
2. 操作步驟
1. 主庫備份表
# mysqldump -uroot -p123123 -h127.0.0.1 --single-transaction --set-gtid-purged=on --triggers --routines --events test t1 >/tmp/t1.sql
2. 查看備份文件
# cat /tmp/t1.sql |egrep SET |egrep -v "^/"SET @MYSQLDUMP_TEMP_LOG_BIN = @@SESSION.SQL_LOG_BIN;SET @@SESSION.SQL_LOG_BIN= 0;SET @@GLOBAL.GTID_PURGED='59fe7a3e-9dd6-11e7-9d6c-000c29e57c69:1-22';) ENGINE=InnoDB DEFAULT CHARSET=latin1;SET @@SESSION.SQL_LOG_BIN = @MYSQLDUMP_TEMP_LOG_BIN;
3. 從庫恢復
> reset master; //清空GTID_EXECUTED -- @@GLOBAL.GTID_PURGED can only be set when @@GLOBAL.GTID_EXECUTED is empty.# mysql -uroot -p123123 test < t1.sql -- 會執行備份文件中的SET @@GLOBAL.GTID_PURGED。> show slave status \GRetrieved_Gtid_Set: 59fe7a3e-9dd6-11e7-9d6c-000c29e57c69:1-22Executed_Gtid_Set: 59fe7a3e-9dd6-11e7-9d6c-000c29e57c69:1-22> start slave;
五、GTID & 備份
1、邏輯備份
1. 與GTID相關的選項:
- --set-gtid-purged=[ON | OFF | AUTO ]
如果ON,
在備份文件中會有以下兩句
SET @@SESSION.SQL_LOG_BIN= 0;SET @@GLOBAL.GTID_PURGED=
若OFF則不寫入
若AUTO,檢測到GTID,自動添加上述語句,反之不加。
主從的Executed_Gtid_Set列表應該是一致的,也就是說,從庫除了除了重做binlog之外,不能在從庫上生成從庫的GTID。
所以,用slave備份搭建slave,應該不記錄binlog(
SET @@SESSION.SQL_LOG_BIN= 0,恢復過程不產生從庫的GTID),使用選項:
--set-gtid-purged=ON
-
--dump-slave、--master-data
在GTID中,不必使用dump-slave、--master-data,
因為GTID中,不再使用傳統復制中的 file 和 pos
2. 備份案列:用slave搭建slave
# mysqldump -uroot -p123123 --single-transaction --routines --events --set-gtid-purged=ON --all-databases >/tmp/10_2.sql# mysql </tmp/10_2.sqlmysql> CHANGE MASTER TO MASTER_HOST = '192.168.234.130', MASTER_PORT = 3306, MASTER_USER = 'repl', MASTER_PASSWORD = 'repl', MASTER_AUTO_POSITION = 1;mysql> start slave;
2、物理備份
備份的時候,只要在備份的時候記錄下Executed_Gtid_Set($gtid_dump)即可,這個可以用於重新change master;
# innobackupex --defaults-file=/export/servers/mysql/etc/my.cnf --slave-info --user=root --password=123123 --no-timestamp /tmp/in.sql# cat xtrabackup_slave_infoSET GLOBAL gtid_purged='29bd8c99-9e4d-11e7-a072-000c29d00b2d:1-5, 59fe7a3e-9dd6-11e7-9d6c-000c29e57c69:1-68';CHANGE MASTER TO MASTER_AUTO_POSITION=1> reset master;> SET @@GLOBAL.GTID_PURGED='$gtid_dump'; //上面備份文件中的值> change master to master_auto_position=1;
六、GTID & 並行復制
1. 為了兼容MySQL 5.6基於庫的並行復制,5.7引入了新的變量slave-parallel-type,其可以配置的值有:
DATABASE:默認值,基於庫的並行復制方式LOGICAL_CLOCK:基於組提交的並行復制方式
2. MySQL 5.7才可稱為真正的並行復制
這其中最為主要的原因就是master服務器上是怎么並行執行的slave上就怎樣進行並行回放,一個組提交的事務都是可以並行回放。
3. 在MySQL 5.7版本中,其設計方式是將組提交的信息存放在GTID中。如果用戶沒有開啟GTID功能,引入了稱之為Anonymous_Gtid的概念。
較之原來的二進制日志內容多了last_committed和sequence_number;
last_committed表示事務提交的時候,上次事務提交的編號,如果事務具有相同的last_committed,表示這些事務都在一組內,可以進行並行的回放。
# mysqlbinlog -vv mysql-bin.000001 |egrep last_commit#171002 11:53:31 server id 1 end_log_pos 219 CRC32 0x4a9095a9 Anonymous_GTID last_committed=0 sequence_number=1#171002 11:53:31 server id 1 end_log_pos 473 CRC32 0x786dd106 Anonymous_GTID last_committed=1 sequence_number=2