Mysql 5.7 Gtid內部學習(八) Gtid帶來的運維改變

gaopengtttt發表於2017-12-18
簡書地址:


依託前文的解析來講5.7中 Gtid帶來的運維改變,我想理解應該是更加深刻,這節主要討論以下幾個部分:

  1. 如何跳過一個事物
  2. mysqldump匯出行為的改變
  3. 5.7中搭建基於Gtid的主從
  4. 5.7中Gtid的主從的切換
  5. 5.7中線上改變Gtid模式

一、如何跳過一個事物

和傳統基於位置的主從不同,如果從庫報錯我們需要獲得從庫執行的最後一個事物,方法有如下:

  • show slave status \G 中的 Executed_Gtid_Set。
  • show global variables like '%gtid%'; 中的 gtid_executed 。
  • show master status;中的Executed_Gtid_Set。

然後構建一個空事物如下:

stop slave ;
set gtid_next='4a6f2a67-5d87-11e6-a6bd-000c29a879a3:34';
begin;commit;
set gtid_next='automatic';
start slave ; 

如果是多個如下:

stop slave ;
set gtid_next='89dfa8a4-cb13-11e6-b504-000c29a879a3:3';
begin;commit;
set gtid_next='89dfa8a4-cb13-11e6-b504-000c29a879a3:4';
begin;commit;
set gtid_next='automatic';
start slave ; 

二、 mysqldump匯出行為的改變

使用mysqldump受到選項set-gtid-purged=AUTO的影響,假如我們在Gtid開啟和關閉的情況下使用如下語句匯出資料:

mysqldump  --single-transaction  --master-data=2  -R -E --triggers  --all-databases 

在Gtid開啟的情況下會多如下設定:

SET @MYSQLDUMP_TEMP_LOG_BIN = @@SESSION.SQL_LOG_BIN;
SET @@SESSION.SQL_LOG_BIN= 0;

--
-- GTID state at the beginning of the backup 
--

SET @@GLOBAL.GTID_PURGED='ec9bdd78-a593-11e7-9315-5254008138e4:1-105'; 

為什麼要這麼設定呢?因為如果做基於Gtid的主從,是否生成binlog就意味著在匯入資料的時候是否基於本地資料庫生成新的Gtid事物,顯然這是不合理的,所以將SQL_LOG_BIN設定為0是必須的。接著GTID_PURGED被設定為備份時刻已經執行過的Gtid事物,如前文第五節原始碼剖析設定GTID_PURGED會設定三個地方的Gtid如下:

  • mysql.gtid_executed表
  • gtid_purge變數
  • gtid_executed變數

看起來是合理的,但是如果這裡忽略了整個mysql.gtid_executed表是innodb表,匯入過程中某些版本(已知percona 5.7.14,5.7.17)會重新刪除和建立,因此透過GTID_PURGED設定的mysql.gtid_executed表會重新改變,重啟資料庫後需要讀取mysql.gtid_executed表可能獲得錯誤Gtid集合導致複製錯誤。這也為我的故障案例埋下了伏筆,案例中在詳細描述。
當然也可以使用 --set-gtid-purged=OFF選項來告訴mysqldump不需要加入SQL_LOG_BIN= 0和GTID_PURGED,但是初始化搭建基於Gtid的主從一定不要設定為OFF。下面是這個選項的含義。

 --set-gtid-purged[=name] 
                      Add 'SET @@GLOBAL.GTID_PURGED' to the output. Possible
                      values for this option are ON, OFF and AUTO. If ON is
                      used and GTIDs are not enabled on the server, an error is
                      generated. If OFF is used, this option does nothing. If
                      AUTO is used and GTIDs are enabled on the server, 'SET
                      @@GLOBAL.GTID_PURGED' is added to the output. If GTIDs
                      are disabled, AUTO does nothing. If no value is supplied
                      then the default (AUTO) value will be considered. 

三、5.7中搭建基於Gtid的主從

這裡存在一個注意點,也是我案例中會提到的。我們還是直接說步驟

  • 注意主備庫必須開啟Gtid和設定好server_id
 enforce_gtid_consistency = ON
 gtid_mode = ON
 server_id = 9910
 binlog_format = row 

同時主備庫都開啟binlog如果不設定級聯從庫,從庫不要設定log_slave_updates引數。
這是最合理的設定。

  • 建立複製使用者
CREATE USER 'repl'@'%' IDENTIFIED BY  'test123';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%' ; 
  • 匯出資料
mysqldump  --single-transaction  --master-data=2  -R -E --triggers  --all-databases > test.sql 
  • 從庫匯入資料
    source即可。

  • 從庫執行reset master語句
    這一步主要防止gtid_executed被更改過。這個問題在在percona 5.7.14 5.7.17存在但是在percona 5.7.15 5.7.19又不存在。所以為了安全還是執行下面的兩步。

reset master; 
  • 提取GTID_PURGED,並且執行
    使用head -n 40 命令可以快速的得到比如我這裡的
--
-- GTID state at the beginning of the backup 
--

SET @@GLOBAL.GTID_PURGED='ec9bdd78-a593-11e7-9315-5254008138e4:1-21'; 

執行

SET @@GLOBAL.GTID_PURGED='ec9bdd78-a593-11e7-9315-5254008138e4:1-21'; 

語句即可,完成本部分mysql.gtid_executed表會重構。

  • 使用MASTER_AUTO_POSITION建立同步
change master to 
master_host='192.168.99.41',
master_user='repl',
master_password='test123',
master_port=3310,
MASTER_AUTO_POSITION = 1; 
  • 啟動slave
start slave 

四、5.7中Gtid的主從的切換

切換中必須要確認從庫(新主庫)沒有做過本地的事物,如果做過,否則切換主庫(新從庫)需要拉取這一部分的Gtid事物,如果這些binlog已經不存在了那麼勢必會報錯。這種情況下還是從建從庫吧。那麼我們來說正常的切換步驟。

  • 從庫(新主庫)
stop slave;
reset slave all; 
  • 主庫(新從庫)
change master to 
master_host='192.168.99.40',
master_user='repl',
master_password='test123',
master_port=3310,
MASTER_AUTO_POSITION = 1;
start slave; 

實際就這麼簡單,從庫(新主庫)會生成自己的Gtid事物,新主庫接受到後執行即可。此時會出現如下有兩個server_uuid對應的Gtid,如下的gtid_executed

mysql> show global variables like '%gtid%';
+----------------------------------+-------------------------------------------------------------------------------------+
| Variable_name                    | Value                                                                               |
+----------------------------------+-------------------------------------------------------------------------------------+
| binlog_gtid_simple_recovery      | ON                                                                                  |
| enforce_gtid_consistency         | ON                                                                                  |
| gtid_executed                    | 31704d8a-da74-11e7-b6bf-525400a7d243:1-9,
ec9bdd78-a593-11e7-9315-5254008138e4:1-25 |
| gtid_executed_compression_period | 1000                                                                                |
| gtid_mode                        | ON                                                                                  |
| gtid_owned                       |                                                                                     |
| gtid_purged                      | ec9bdd78-a593-11e7-9315-5254008138e4:1-25                                           |
| session_track_gtids              | OFF                                                                                 |
+----------------------------------+-------------------------------------------------------------------------------------+ 

總的說來如果要作為的切換的從庫,不要在從庫本地做任何事物。如果確實要做比如加索引等不影響資料的操作可以是使用如下:

mysql> set sql_log_bin=0;
Query OK, 0 rows affected (0.00 sec)

mysql> create index test_jjj on jjj(id);
Query OK, 0 rows affected (0.42 sec)
Records: 0  Duplicates: 0  Warnings: 0 

這樣也是不會增加本地Gtid的。

五、線上修改Gtid模式

這是5.7.6以後實現的功能其主要依賴了我們前面分析的 Previous gtid Event以及引數gtid_mode新加入的2個值。我們具體來看看gitd_mode各個值的含義:

  • OFF(0): Both new and replicated transactions must be anonymous.(生成的是匿名事物,slave也只能應用匿名事物)
  • OFF_PERMISSIVE:(1) New transactions are anonymous. Replicated transactions can be either
    anonymous or GTID transactions.(生成的是匿名事物,slave可以應用匿名和GTID事物)
  • ON_PERMISSIVE(2): New transactions are GTID transactions. Replicated transactions can be either
    anonymous or GTID transactions.(生成的是GTID事物,slave可以應用匿名和GTID事物)
  • ON(3): Both new and replicated transactions must be GTID transactions(生成的是GTID事物,slave也只能應用GTID事物)

注意每次修改值必然導致一次binlog的切換,如果發生binlog刪除也能夠依託 Previous gtid Event快速準確的找到gtid_purged(Gtid_state.lost_gtids)。

線上啟動
  • 主庫/從庫執行
SET @@GLOBAL.ENFORCE_GTID_CONSISTENCY = WARN; 

確定事物都支援gtid,不會在err log中出現警告如下:
2017-02-26T22:35:24.322055Z 55 [Warning] Statement violates GTID consistency: CREATE TABLE ... SELECT.

  • 主庫/從庫執行
SET @@GLOBAL.ENFORCE_GTID_CONSISTENCY = ON; 
  • 主庫/從庫執行
SET @@GLOBAL.GTID_MODE = OFF_PERMISSIVE; 

生成的是匿名事物,slave可以應用匿名和GTID事物

  • 主庫/從庫執行
SET @@GLOBAL.GTID_MODE = ON_PERMISSIVE; 

生成的是GTID事物,slave可以應用匿名和GTID事物

  • 主庫/從庫執行

確定已經沒有匿名的事物

SHOW GLOBAL STATUS LIKE 'ONGOING_ANONYMOUS_TRANSACTION_COUNT'; 

同時確認從庫
Retrieved_Gtid_Set
Executed_Gtid_Set
正常增長

到這一步實際上gtid事物已經開始使用了。

  • 主庫/從庫執行
SET @@GLOBAL.GTID_MODE = ON; 
  • 從庫執行
stop slave;
CHANGE MASTER TO MASTER_AUTO_POSITION = 1;
start slave; 
  • 主庫/從庫執行
    修改配置檔案my.cnf,將引數的更改加入到配置檔案
線上關閉
  • 從庫執行
stop slave; 

記錄從庫執行狀態值

Exec_Master_Log_Pos: 7631438
Relay_Master_Log_File: bin_log.000016 

執行

CHANGE MASTER TO MASTER_AUTO_POSITION = 0,
MASTER_LOG_FILE = 'bin_log.000016', 
MASTER_LOG_POS = 7631438
start slave; 
  • 主庫/從庫執行
SET @@GLOBAL.GTID_MODE = ON_PERMISSIVE; 

生成的是GTID事物,slave可以應用匿名和GTID事物

  • 主庫/從庫執行
SET @@GLOBAL.GTID_MODE = OFF_PERMISSIVE; 

生成的是匿名事物,slave可以應用匿名和GTID事物

  • 從庫執行

等待從庫
Retrieved_Gtid_Set
Executed_Gtid_Set
不再變動。
完成這一步實際上GTID事物已經沒有生成和應用了

  • 主庫/從庫執行
SET @@GLOBAL.GTID_MODE = OFF; 
  • 主庫/從庫執行

修改配置檔案my.cnf,將引數的更改加入到配置檔案

六、總結

學習完本節至少能夠學習到:

  • 如何跳過一個事物
  • mysqldump匯出行為的改變
  • 5.7中搭建基於Gtid的主從
  • 5.7中Gtid的主從的切換
  • 5.7中線上改變Gtid 模式

關於其他運維可以參考官方文件:

  • Chapter 18 Replication

作者微信:


微信.jpg

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-2148841/,如需轉載,請註明出處,否則將追究法律責任。

相關文章