GTID


一、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

三、GTID主從復制

2.1 GTID的工作原理

  1. 當一個事務在主庫端執行並提交時,產生GTID,一同記錄到binlog日志中 [SET @@SESSION.GTID_NEXT]。
  2. binlog傳輸到slave,並存儲到slave的relaylog后,開始重做。
  3. 執行SET @@SESSION.GTID_NEXT,從庫對比[Executed_Gtid_Set] 是否執行過。
  4. 如果有記錄,說明該GTID的事務已經執行,slave會忽略;
  5. 如果沒有記錄,
    1. 在讀取執行事務前會先檢查其他session持有該GTID,確保不被重復執行。
    2. slave就會執行該GTID事務,並記錄[Executed_Gtid_Set],
注意:從庫執行relay log ,記錄binlog時,還是記錄主庫的GTID,不會產生新的GTID號

2.2 啟動GTID的關鍵步驟

由最初的GTID復制拓撲(包括一個主站和一個從站)構成的啟動過程中的關鍵步驟如下:
  1. 如果復制已經在運行,則通過使這兩個服務器成為只讀方式來同步.
    1. mysql> SET @@global.read_only = ON;
  2. 停止兩個服務器。
    1. shell> mysqladmin -uusername -p shutdown;
  3. 重新啟動啟用GTID的兩個服務器,並配置正確的選項。
    1. gtid_mode=ON 
    2. enforce-gtid-consistency=true
  4. 指示從機使用主機作為復制數據源,並使用自動定位,然后啟動從機。
    1. mysql> CHANGE MASTER TO> MASTER_HOST = host, MASTER_PORT = port, MASTER_USER = user, MASTER_PASSWORD = password, MASTER_AUTO_POSITION = 1;
    2. mysql> START SLAVE;
  5. 在兩台服務器上再次啟用讀取模式,以便它們可以接受更新。
    1. 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,可以用命令:
logged_gtids 用來判斷 MySQL 有沒有執行某個事務。例如,在 Master 發送  binlog 時,MySQL 5.6 能夠根據 Slave 提供的 logged_gtids 記錄,自動過濾  binlog 中不需要執行的事務
2. gtid_purged
記錄從  binlog 刪除的全局事務 ID 集合。它對應的 MySQL Global variable 是:gtid_purged 。
每當 MySQL 5.6 調用 purge_logs 刪除 binlog 時,會順帶更新 gtid_purged 的內容。這是通過讀剩下的 binlog 文件實現的
3.  gtid_owned
正在由線程執行的全局事務 ID 集合。它對應的 MySQL variable 是:gtid_owned
4. gtid_next
  • 取值:
    • 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 \G
          Last_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 exist
          Retrieved_Gtid_Set: 59fe7a3e-9dd6-11e7-9d6c-000c29e57c69:1-17
          Executed_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 \G
          Retrieved_Gtid_Set: 59fe7a3e-9dd6-11e7-9d6c-000c29e57c69:1-22
          Executed_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.sql 
mysql> 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_info
SET 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

     


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM