MySQL5.6 新特性之GTID

背景:html

      MySQL5.6在5.5的基礎上增長了一些改進,本文章先對其中一個一個比較大的改進"GTID"進行說明。mysql

概念:sql

      GTID即全局事務ID(global transaction identifier),GTID其實是由UUID+TID組成的。其中UUID是一個MySQL實例的惟一標識。TID表明了該實例上已經提交的事務數量,而且隨着事務提交單調遞增,因此GTID可以保證每一個MySQL實例事務的執行(不會重複執行同一個事務,而且會補全沒有執行的事務)。下面是一個GTID的具體形式:安全

4e659069-3cd8-11e5-9a49-001c4270714e:1-77

更具體的說明見官方說明服務器

GTID意義:session

      引入GTID的意義是什麼?ide

      1)由於清楚了GTID的格式,因此經過UUID能夠知道這個事務在哪一個實例上提交的。工具

      2)經過GTID能夠極方便的進行復制結構上的故障轉移,新主設置。很好的解決了下面這個圖(圖來自高性能MySQL第10章)的問題。
性能

上面圖的意思是:Server1(Master)崩潰,根據從上show slave status得到Master_log_File/Read_Master_Log_Pos的值,Server2(Slave)已經跟上了主,Server3(Slave)沒有跟上主。這時要是把Server2提高爲主,Server3變成Server2的從。這時在Server3上執行change的時候須要作一些計算,這裏就不作說明了,具體的說明見高性能MySQL第10章,相對來講是比較麻煩的。測試

這個問題在5.6的GTID出現後,就顯得很是的簡單。因爲同一事務的GTID在全部節點上的值一致,那麼根據Server3當前中止點的GTID就能定位到Server2上的GTID。甚至因爲MASTER_AUTO_POSITION功能的出現,咱們都不須要知道GTID的具體值,直接使用CHANGE MASTER TO MASTER_HOST='xxx', MASTER_AUTO_POSITION命令就能夠直接完成failover的工做。

原理:

      從服務器鏈接到主服務器以後,把本身執行過的GTID(Executed_Gtid_Set)<SQL線程> 、獲取到的GTID(Retrieved_Gtid_Set)<IO線程>發給主服務器,主服務器把從服務器缺乏的GTID及對應的transactions發過去補全便可。當主服務器掛掉的時候,找出同步最成功的那臺從服務器,直接把它提高爲主便可。若是硬要指定某一臺不是最新的從服務器提高爲主, 先change到同步最成功的那臺從服務器, 等把GTID所有補全了,就能夠把它提高爲主了。

測試:

1)複製環境的搭建:具體的複製搭建的步驟能夠在網上搜索

由於支持GTID,因此5.6多了幾個參數:

mysql> show variables like '%gtid%';
+---------------------------------+-----------+
| Variable_name                   | Value     |
+---------------------------------+-----------+
| binlog_gtid_simple_recovery     | OFF       |
| enforce_gtid_consistency        | OFF       |
| gtid_deployment_step            | OFF       |
| gtid_executed                   |           |
| gtid_mode                       | OFF       |
| gtid_next                       | AUTOMATIC |
| gtid_owned                      |           |
| gtid_purged                     |           |
| simplified_binlog_gtid_recovery | OFF       |
+---------------------------------+-----------+

主從環境的搭建和5.5沒有什麼區別,惟一須要注意的是:開啓GTID須要啓用這三個參數:

#GTID
gtid_mode = on enforce_gtid_consistency = 1 log_slave_updates = 1

任意一個參數不開啓則都會報錯:

2015-08-09 02:33:57 6512 [ERROR] --gtid-mode=ON or UPGRADE_STEP_1 or UPGRADE_STEP_2 requires --log-bin and --log-slave-updates
2015-08-09 02:33:57 6512 [ERROR] Aborting

2015-08-09 02:39:58 9860 [ERROR] --gtid-mode=ON or UPGRADE_STEP_1 requires --enforce-gtid-consistency
2015-08-09 02:39:58 9860 [ERROR] Aborting

具體的方法能夠參考官方文檔

三個實例開啓以後(330六、330七、3308),執行change的時候也要注意:

各個實例的uuid:

3306:
mysql> select @@server_uuid;
+--------------------------------------+
| @@server_uuid                        |
+--------------------------------------+
| 4e659069-3cd8-11e5-9a49-001c4270714e |
+--------------------------------------+

3307:
mysql> select @@server_uuid;
+--------------------------------------+
| @@server_uuid                        |
+--------------------------------------+
| 041d0e65-3cde-11e5-9a6e-001c4270714e |
+--------------------------------------+

3308:
mysql> select @@server_uuid;
+--------------------------------------+
| @@server_uuid                        |
+--------------------------------------+
| 081ccacf-3ce4-11e5-9a95-001c4270714e |
+--------------------------------------+

使用5.6以前的主從change:

mysql> change master to master_host='127.0.0.1',master_user='rep',master_password='rep',master_log_file='mysql-bin3306.000001',master_log_pos=151,/*master_auto_position=1*/;

報錯:

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.

當使用 MASTER_AUTO_POSITION 參數的時候,MASTER_LOG_FILE,MASTER_LOG_POS參數不能使用。

使用5.6以後的主從change:

mysql> change master to master_host='127.0.0.1',master_user='rep',master_password='rep',master_port=3306,master_auto_position=1;

在執行上面的命令的時候會報錯2個warnings,主要的緣由是複製帳號安全的問題,相關的信息能夠看這裏

從整體上看來,因爲要支持GTID,因此不須要手工肯定主服務器的MASTER_LOG_FILE及MASTER_LOG_POS。要是不須要GTID則須要指定FILE和POS。在2個從上執行上面命令,到此主從環境搭建完成。GTID的主從完成以後能夠經過show processlist查看:

mysql> show processlist\G;
*************************** 1. row ***************************
           Id: 38
         User: rep
         Host: localhost:52321
           db: NULL Command: Binlog Dump GTID #經過GTID複製
         Time: 48
        State: Master has sent all binlog to slave; waiting for binlog to be updated
         Info: NULL
    Rows_sent: 0
Rows_examined: 0

2)測試複製的故障轉移

server1(3306)掛了,服務器起不來了。須要把其中的一個從設置爲主,另外一個設置爲其的從庫:

server2(3307):

              Master_Log_File: mysql-bin3306.000002
          Read_Master_Log_Pos: 4156773
          Exec_Master_Log_Pos: 4156773

server3(3308):

              Master_Log_File: mysql-bin3306.000001
          Read_Master_Log_Pos: 83795320
          Exec_Master_Log_Pos: 83795320

相比之下server2完成的事務要比server3更接近或則等於server1,如今須要把server3設置爲server2的從庫。

在MySQL5.6以前,這裏的計算會很麻煩,要計算以前主庫的log_pos和當前要設置成主庫的log_pos,頗有可能出錯。因此出現了一些高可用性的工具如MHA,MMM等解決問題。

在MySQL5.6以後,很簡單的解決了這個難題。由於同一事務的GTID在全部節點上的值一致,那麼根據server3當前中止點的GTID就能定位到server2上的GTID,因此直接在server3上執行change便可:

mysql> stop slave;
Query OK, 0 rows affected (0.02 sec)

#千萬不要執行 reset master,不然會從最早的GTID上開始執行。 mysql
> change master to master_host='127.0.0.1',master_user='rep',master_password='rep',master_port=3307,master_auto_position=1; #指定到另外一個比較接近主的從上。 Query OK, 0 rows affected, 2 warnings (0.02 sec) mysql> start slave; #成功的切換到新主 Query OK, 0 rows affected (0.03 sec)

主從結構已經變動,server2是Master,server3是Slave。由於不須要計算pos的值,因此經過GTID很簡單的解決了這個問題。

3)跳過複製錯誤:gtid_next、gtid_purged

 從服務器跳過一個錯誤的事務:

mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 127.0.0.1
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin3306.000001
          Read_Master_Log_Pos: 38260944
               Relay_Log_File: mysqld-relay-bin3307.000002
                Relay_Log_Pos: 369
        Relay_Master_Log_File: mysql-bin3306.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: No
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 1008
                   Last_Error: Error 'Can't drop database 'mablevi'; database doesn't exist' on query. Default database: 'mablevi'. Query: 'drop database mablevi'
                 Skip_Counter: 0 Exec_Master_Log_Pos: 151
              Relay_Log_Space: 38261371
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File: 
           Master_SSL_CA_Path: 
              Master_SSL_Cert: 
            Master_SSL_Cipher: 
               Master_SSL_Key: 
        Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 1008 Last_SQL_Error: Error 'Can't drop database 'mablevi'; database doesn't exist' on query. Default database: 'mablevi'. Query: 'drop database mablevi'
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 1
                  Master_UUID: 4e659069-3cd8-11e5-9a49-001c4270714e
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0  #經過在change的時候指定,如:change master to master_delay=600,延遲10分鐘同步。
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: 
           Master_Retry_Count: 86400
                  Master_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 150810 23:38:39
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: 4e659069-3cd8-11e5-9a49-001c4270714e:1-48 Executed_Gtid_Set: 
                Auto_Position: 1

在MySQL5.6以前,只須要執行:

mysql> set global sql_slave_skip_counter=1

跳過一個錯誤的事務,就能夠繼續進行復制了。但在MySQL5.6以後則不行:

mysql> set global sql_slave_skip_counter=1;
ERROR 1858 (HY000): sql_slave_skip_counter can not be set when the server is running with @@GLOBAL.GTID_MODE = ON. Instead, for each transaction that you want to skip, generate an empty transaction with the same GTID as the transaction

分析:由於是經過GTID來進行復制的,也須要跳過這個事務從而繼續複製,這個事務能夠到主上的binlog裏面查看:由於不知道找哪一個GTID上出錯,因此也不知道如何跳過哪一個GTID。但在show slave status裏的信息裏能夠找到在執行Master裏的POS:151

Exec_Master_Log_Pos: 151

的時候報錯,因此經過mysqlbinlog找到了GTID:

# at 151
#150810 22:57:45 server id 1  end_log_pos 199 CRC32 0x5e14d88f     GTID [commit=yes]
SET @@SESSION.GTID_NEXT= '4e659069-3cd8-11e5-9a49-001c4270714e:1'/*!*/;

找到這個GTID以後執行:必須按照下面順序執行

mysql> stop slave;
Query OK, 0 rows affected (0.01 sec)

mysql> set session gtid_next='4e659069-3cd8-11e5-9a49-001c4270714e:1';  #在session裏設置gtid_next,即跳過這個GTID
Query OK, 0 rows affected (0.01 sec)

mysql> begin;      #開啓一個事務
Query OK, 0 rows affected (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.01 sec)

mysql> SET SESSION GTID_NEXT = AUTOMATIC;   #把gtid_next設置回來
Query OK, 0 rows affected (0.00 sec)

mysql> start slave;  #開啓複製
Query OK, 0 rows affected (0.01 sec)

查看複製狀態:

mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 127.0.0.1
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin3306.000001
          Read_Master_Log_Pos: 38260944
               Relay_Log_File: mysqld-relay-bin3307.000003
                Relay_Log_Pos: 716
        Relay_Master_Log_File: mysql-bin3306.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 38260944
              Relay_Log_Space: 38261936
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File: 
           Master_SSL_CA_Path: 
              Master_SSL_Cert: 
            Master_SSL_Cipher: 
               Master_SSL_Key: 
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 1
                  Master_UUID: 4e659069-3cd8-11e5-9a49-001c4270714e
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0  #延遲同步
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
           Master_Retry_Count: 86400
                  Master_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: 4e659069-3cd8-11e5-9a49-001c4270714e:1-48 Executed_Gtid_Set: 4e659069-3cd8-11e5-9a49-001c4270714e:1-48
                Auto_Position: 1

在此成功跳過了錯誤,同步繼續。能夠經過這個辦法來處理複製失敗的問題,這裏還有個例子,有興趣的能夠看一下(從服務器中跳過一條語句/事務):

mysql > stop slave;
Query OK, 0 ROWS affected (0.05 sec)
mysql > CHANGE master TO MASTER_DELAY=600;
Query OK, 0 ROWS affected (0.27 sec)
mysql > START slave;
Query OK, 0 ROWS affected, 1 warning (0.06 sec)

master 本來是正常的, 而後意外地執行了 truncate table:

mysql > INSERT INTO t SET title='c';
Query OK, 1 ROW affected (0.03 sec)
mysql > INSERT INTO t SET title='d';
Query OK, 1 ROW affected (0.05 sec)

mysql > SHOW master STATUS \G
*************************** 1. ROW ***************************
             File: black-bin.000001
         POSITION: 2817
     Binlog_Do_DB: 
 Binlog_Ignore_DB: 
Executed_Gtid_Set: 0c005b76-d3c7-11e2-a27d-274c063b18c4:1-10
1 ROW IN SET (0.00 sec)

mysql > TRUNCATE TABLE t;
Query OK, 0 ROWS affected (0.15 sec)

mysql > SHOW master STATUS \G
*************************** 1. ROW ***************************
             File: black-bin.000001
         POSITION: 2948
     Binlog_Do_DB: 
 Binlog_Ignore_DB: 
Executed_Gtid_Set: 0c005b76-d3c7-11e2-a27d-274c063b18c4:1-11
1 ROW IN SET (0.00 sec)

slave有延遲, 雖然已經獲取到了gtid及對應的events, 可是並未執行:

mysql > SHOW slave STATUS \G
*************************** 1. ROW ***************************
               Slave_IO_State: Waiting FOR master TO send event
.......
.......
                    SQL_Delay: 600
          SQL_Remaining_Delay: 565
      Slave_SQL_Running_State: Waiting until MASTER_DELAY seconds after master executed event
           Master_Retry_Count: 86400
                  Master_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: 0c005b76-d3c7-11e2-a27d-274c063b18c4:9-11
            Executed_Gtid_Set: 0c005b76-d3c7-11e2-a27d-274c063b18c4:1-8
                Auto_Position: 1
1 ROW IN SET (0.00 sec)

要想辦法在slave中跳過 GTID:0c005b76-d3c7-11e2-a27d-274c063b18c4:11, 也就是那條truncate table語句 。
辦法就是設置GTID_NEXT,而後提交一個空的事務。

mysql > stop slave;
Query OK, 0 ROWS affected (0.03 sec)
mysql > SET session gtid_next='0c005b76-d3c7-11e2-a27d-274c063b18c4:11';
Query OK, 0 ROWS affected (0.00 sec)
mysql > BEGIN; commit;
Query OK, 0 ROWS affected (0.00 sec)
Query OK, 0 ROWS affected (0.01 sec)

mysql >SET SESSION GTID_NEXT = AUTOMATIC;
Query OK, 0 ROWS affected (0.00 sec)
mysql > START slave;
Query OK, 0 ROWS affected, 1 warning (0.07 sec)

查看複製狀態
mysql > SHOW slave STATUS \G
*************************** 1. ROW ***************************
               Slave_IO_State: Waiting FOR master TO send event
.......
.......
            Retrieved_Gtid_Set: 0c005b76-d3c7-11e2-a27d-274c063b18c4:9-11
            Executed_Gtid_Set: 0c005b76-d3c7-11e2-a27d-274c063b18c4:1-11
                Auto_Position: 1
1 ROW IN SET (0.00 sec)

mysql > SELECT * FROM t;
+----+-------+
| id | title |
+----+-------+
|  1 | a     |
|  2 | b     |
|  3 | c     |
|  4 | d     |
+----+-------+
4 ROWS IN SET (0.00 sec)

成功跳過 truncate table, 固然此時主從的數據已經不一致了。
View Code

注意:經過GTID的複製都是沒有指定MASTER_LOG_FILE和MASTER_LOG_POS的,因此經過GTID複製都是從最早開始的事務開始,除非在本身的binlog裏面有執行過以前的記錄,纔會繼續後面的執行。

要是事務日誌被purge,再進行change:

mysql> show master logs;   
+----------------------+-----------+
| Log_name             | File_size |
+----------------------+-----------+
| mysql-bin3306.000001 |  38260944 |
+----------------------+-----------+
1 row in set (0.00 sec)

mysql> flush logs;
Query OK, 0 rows affected (0.03 sec)

mysql> show tables;
+---------------+
| Tables_in_mmm |
+---------------+
| patent_family |
| t1            |
| t2            |
+---------------+
3 rows in set (0.01 sec)

mysql> create table t3(id int)engine = tokudb;
Query OK, 0 rows affected (0.02 sec)

mysql> insert into t3 values(3),(4);
Query OK, 2 rows affected (0.05 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> flush logs;
Query OK, 0 rows affected (0.02 sec)

mysql> create table ttt(id int)engine = tokudb;
Query OK, 0 rows affected (0.02 sec)

mysql> insert into ttt values(1),(2),(3),(4),(5);
Query OK, 5 rows affected (0.03 sec)
Records: 5  Duplicates: 0  Warnings: 0

mysql> show master logs;
+----------------------+-----------+
| Log_name             | File_size |
+----------------------+-----------+
| mysql-bin3306.000001 |  38260995 |
| mysql-bin3306.000002 |       656 |
| mysql-bin3306.000003 |       619 |
+----------------------+-----------+
3 rows in set (0.00 sec)

mysql> purge binary logs to 'mysql-bin3306.000003';  #日誌被purge
Query OK, 0 rows affected (0.02 sec)

mysql> show master logs;   #日誌被purge以後等下的binlog 
+----------------------+-----------+
| Log_name             | File_size |
+----------------------+-----------+
| mysql-bin3306.000003 |       619 |
+----------------------+--------

3308登錄以後執行:

mysql> change master to master_host='127.0.0.1',master_user='rep',master_password='rep',master_port=3306,master_auto_position=1;
Query OK, 0 rows affected, 2 warnings (0.04 sec)

mysql> start slave;
Query OK, 0 rows affected (0.02 sec)

mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: 
                  Master_Host: 127.0.0.1
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: 
          Read_Master_Log_Pos: 4
               Relay_Log_File: mysqld-relay-bin3308.000001
                Relay_Log_Pos: 4
        Relay_Master_Log_File: 
             Slave_IO_Running: No
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 0
              Relay_Log_Space: 151
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File: 
           Master_SSL_CA_Path: 
              Master_SSL_Cert: 
            Master_SSL_Cipher: 
               Master_SSL_Key: 
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 1236
                Last_IO_Error: 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.'
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 1
                  Master_UUID: 4e659069-3cd8-11e5-9a49-001c4270714e
             Master_Info_File: /var/lib/mysql3/master.info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
           Master_Retry_Count: 86400
                  Master_Bind: 
      Last_IO_Error_Timestamp: 150811 00:02:50
     Last_SQL_Error_Timestamp: 
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: 
            Executed_Gtid_Set: 
                Auto_Position: 1
View Code

報錯:

                Last_IO_Errno: 1236
                Last_IO_Error: 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.'

這裏須要解決的是:Slave如何跳過purge的部分,而不是在最早開始的事務執行。

在主上執行,查看被purge的GTID:
mysql> show global variables like 'gtid_purged';
+---------------+-------------------------------------------+
| Variable_name | Value                                     |
+---------------+-------------------------------------------+
| gtid_purged   | 4e659069-3cd8-11e5-9a49-001c4270714e:1-50 |
+---------------+-------------------------------------------+
1 row in set (0.00 sec)

在從上執行,跳過這個GTID:
mysql> stop slave;
Query OK, 0 rows affected (0.00 sec)

mysql> set global gtid_purged = '4e659069-3cd8-11e5-9a49-001c4270714e:1-50';
Query OK, 0 rows affected (0.02 sec)

mysql> reset master;
Query OK, 0 rows affected (0.04 sec)

mysql> start slave;
Query OK, 0 rows affected (0.01 sec)


要是出現:
ERROR 1840 (HY000): @@GLOBAL.GTID_PURGED can only be set when @@GLOBAL.GTID_EXECUTED is empty.
則須要執行:
reset master;

到這從的同步就正常了。 

mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 127.0.0.1
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin3306.000003
          Read_Master_Log_Pos: 619
               Relay_Log_File: mysqld-relay-bin3308.000002
                Relay_Log_Pos: 797
        Relay_Master_Log_File: mysql-bin3306.000003
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 619
              Relay_Log_Space: 1006
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File: 
           Master_SSL_CA_Path: 
              Master_SSL_Cert: 
            Master_SSL_Cipher: 
               Master_SSL_Key: 
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 1
                  Master_UUID: 4e659069-3cd8-11e5-9a49-001c4270714e
             Master_Info_File: /var/lib/mysql3/master.info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
           Master_Retry_Count: 86400
                  Master_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: 4e659069-3cd8-11e5-9a49-001c4270714e:51-52
            Executed_Gtid_Set: 4e659069-3cd8-11e5-9a49-001c4270714e:1-52
                Auto_Position: 1
1 row in set (0.00 sec)

mysql> use mmm
Database changed
mysql> show tables;
+---------------+
| Tables_in_mmm |
+---------------+
| ttt           |
+---------------+
1 row in set (0.00 sec)
View Code

③ 經過另外一個從庫恢復從庫數據

好比一臺從庫誤操做,數據丟失了,能夠經過另外一個從庫來進行恢復:

slave2(3308):
mysql> use mmm
Database changed
mysql> show tables;
+---------------+
| Tables_in_mmm |
+---------------+
| patent_family |
| t             |
| tt            |
+---------------+
3 rows in set (0.00 sec)

mysql> truncate table tt;  #誤操做,把記錄刪除了
Query OK, 0 rows affected (0.02 sec)

mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 127.0.0.1
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin3306.000001
          Read_Master_Log_Pos: 38260553
               Relay_Log_File: mysqld-relay-bin3308.000002
                Relay_Log_Pos: 38260771
        Relay_Master_Log_File: mysql-bin3306.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 38260553
              Relay_Log_Space: 38260980
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File: 
           Master_SSL_CA_Path: 
              Master_SSL_Cert: 
            Master_SSL_Cipher: 
               Master_SSL_Key: 
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 1
                  Master_UUID: 4e659069-3cd8-11e5-9a49-001c4270714e
             Master_Info_File: /var/lib/mysql3/master.info
                    SQL_Delay: 0  #延遲同步
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
           Master_Retry_Count: 86400
                  Master_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: 4e659069-3cd8-11e5-9a49-001c4270714e:1-46 Executed_Gtid_Set: 081ccacf-3ce4-11e5-9a95-001c4270714e:1, #多出了一個GTID(自己實例執行的事務)
4e659069-3cd8-11e5-9a49-001c4270714e:1-46
                Auto_Position: 1

數據被誤刪除以後,最好中止複製:stop slave;

恢復數據從slave1(3307)上備份數據,並還原到slave2(3308)中。
備份:
mysqldump  -uzjy -p123456 -h127.0.0.1 -P3307 --default-character-set=utf8 --set-gtid-purged=ON -B mmm > mmm1.sql


在還原到slave2的時候須要在slave2上執行:reset master; 否則會報錯:
ERROR 1840 (HY000) at line 24: @@GLOBAL.GTID_PURGED can only be set when @@GLOBAL.GTID_EXECUTED is empty.

還原:
root@zjy:~# mysql -uzjy -p123456 -h127.0.0.1 -P3308 --default-character-set=utf8 < mmm.sql 

開啓同步:
mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.03 sec)

這時候你會發現誤刪除的數據已經被還原,而且複製也正常。由於根據GTID的原理,經過slave1的備份直接能夠和Master進行同步。

這裏備份注意的一點是:在備份開啓GTID的實例裏,須要指定 --set-gtid-purged參數,不然會報warning:

Warning: A partial dump from a server that has GTIDs will by default include the GTIDs of all transactions, even those that changed suppressed parts of the database. If you don't want to restore GTIDs, pass --set-gtid-purged=OFF. To make a complete dump, pass --all-databases --triggers --routines --events

備份文件裏面會出現:

SET @@GLOBAL.GTID_PURGED='4e659069-3cd8-11e5-9a49-001c4270714e:1-483';

還原的時候會要求先在實例上reset master,否則會報錯:

Warning: Using a password on the command line interface can be insecure.
ERROR 1840 (HY000) at line 24: @@GLOBAL.GTID_PURGED can only be set when @@GLOBAL.GTID_EXECUTED is empty.

指定--set-gtid-purged=ON參數,出現GTID_PURGED,直接還原的時候執行,從庫不須要其餘操做就能夠直接change到主。關於GTID更多的信息能夠到官方文檔裏查看。 

總結:

      GTID就是全局事務ID(global transaction identifier ),最初由google實現,官方MySQL在5.6才加入該功能。要是主從結構只有一臺Master和一臺Slave對於GTID來講就沒有優點了,而對於2臺主以上的結構優點異常明顯,能夠在數據不丟失的狀況下切換新主。
      使用GTID須要注意的是:在構建主從複製以前,在一臺將成爲主的實例上進行一些操做(如數據清理等),經過GTID複製,這些在主從成立以前的操做也會被複制到從服務器上,引發複製失敗。即:經過GTID複製都是從最早開始的事務日誌開始,即便這些操做在複製以前執行。好比在server1上執行一些drop、delete的清理操做,接着在server2上執行change的操做,會使得server2也進行server1的清理操做。

 

參考文章:

http://dev.mysql.com/doc/refman/5.6/en/replication-gtids.html

http://www.cnblogs.com/cenalulu/p/4309009.html

http://mysqllover.com/?p=594

http://forum.z27315.com/topic/22781-mysql56%E4%B8%BB%E4%BB%8E%E5%A4%8D%E5%88%B6/

www.zhaokunyao.com/archives/4131

相關文章
相關標籤/搜索