MySQL 8 複製(五)——配置GTID複製

lhrbest發表於2020-02-12

MySQL 8 複製(五)——配置GTID複製


目錄


一、配置GTID複製


1. 聯機配置GTID複製


2. 聯機更改複製模式


3. GTID相關係統變數


二、GTID運維


1. 跳過一個事務


2. mysqldump匯出


3. 主從切換


三、GTID限制


四、GTID集合運算函式


1. GTID內建函式


2. 使用者自定義函式


3. 使用示例


       上篇解釋了許多GTID的原理,以及在MySQL複製中所起的作用,並且進行了很多實驗加以輔助說明。本篇演示如何從頭開始一步步配置GTID複製。實驗環境同https://wxy0327.blog.csdn.net/article/details/90081518#%E4%BA%8C%E3%80%81%E5%A4%8D%E5%88%B6%E5%AE%9E%E9%AA%8C%E7%8E%AF%E5%A2%83。這裡只討論在聯機情況下進行配置,因為相對於空庫或離線等理想情況,聯機配置複製的需求更為典型和常見。


一、配置GTID複製

1. 聯機配置GTID複製

        依照以前討論非同步複製時得出的結論,本實驗使用XtraBackup工具進行聯機資料備份。主、從伺服器已經進行了以下配置:


在主庫上建立複製專屬使用者。

在主、從庫安裝XtraBackup。

配置主庫到從庫的SSH免密碼連線。

停止作為從庫的MySQL例項,並清空其資料目錄。

        這些作為配置MySQL複製的前置步驟,具體操作參考:https://wxy0327.blog.csdn.net/article/details/90081518#3.%20%E8%81%94%E6%9C%BA。現在說明聯機配置GTID複製的步驟。


(1)檢查主庫中是否有不支援GTID的操作


set global enforce_gtid_consistency=warn;

        讓伺服器在正常工作負載下執行一段時間並監控錯誤日誌,最好包含一天負載最高的時間段,有條件建議觀察2-3天。如果此步驟導致錯誤日誌中出現任何警告,需要調整應用程式,使其僅使用與GTID相容的功能,並且不能生成與GTID相關的任何警告。這是一個重要步驟,在進行下一步之前,必須確保錯誤日誌中未生成警告。


(2)在主庫聯機設定GTID相關引數


set global enforce_gtid_consistency=true;

set global gtid_mode=off_permissive;

set global gtid_mode=on_permissive;

set global gtid_mode=on;

        enforce-gtid-consistency啟用後,MySQL伺服器通過僅允許執行使GTID安全的語句來強制GTID一致性。在啟用基於GTID的複製之前,必須將此選項設定為true。enforce_gtid_consistency的可配置值為:


false:允許事務違反GTID一致性。

true:不允許事務違反GTID一致性。

warn:允許事務違反GTID一致性,但在這種情況下會生成警告。

        當enforce_gtid_consistency設定為true時,只能使用GTID安全的語句,例如如下操作不能與此選項一起使用:


CREATE TABLE ... SELECT語句

在事務內建立TEMPORARY TABLE或DROP TEMPORARY TABLE語句

更新事務和非事務表的事務或語句。

        enforce_gtid_consistency僅在語句進行二進位制日誌記錄時生效。如果在伺服器上禁用了二進位制日誌記錄,或者由於過濾器刪除了語句而未將語句寫入二進位制日誌,則不會對未記錄的語句檢查或強制執行GTID一致性。


        在包含gtid_mode系統變數的所有MySQL版本中,它都可以設定成on或off。MySQL 5.7.6之後gtid_mode提供了兩個新的選項分別為on_permissive和off_permissive。當gtid_mode = on時,無法複製匿名事務,而當gtid_mode = off時,只能複製匿名事務。當gtid_mode = off_permissive時,新事務是匿名的,同時允許複製的事務是GTID或匿名事務。當gtid_mode = on_permissive時,新事務使用GTID,同時允許複製事務為GTID或匿名事務。這意味著可以擁有一個複製拓撲,其中包含使用匿名和GTID事務的伺服器。例如,具有gtid_mode = on的主庫可以有使用gtid_mode = on_permissive從庫。gtid_mode在主從庫上的相容性以及能否使用自動定位如下表所示,每個條目的含義如下:

. Y:主庫和從庫的gtid_mode相容

. N:主庫和從庫的gtid_mode不相容

. *:自動定位可與此組合一起使用




        聯機設定gtid_mode時,只能基於OFF、OFF_PERMISSIVE、ON_PERMISSIVE、ON順序一次改變一步。例如,如果gtid_mode當前設定為OFF_PERMISSIVE,則可以更改為OFF或ON_PERMISSIVE,但不能直接更改為ON,否則會報以下錯誤:


ERROR 1788 (HY000): The value of @@GLOBAL.GTID_MODE can only be changed one step at a time: OFF <-> OFF_PERMISSIVE <-> ON_PERMISSIVE <-> ON. Also note that this value must be stepped up or down simultaneously on all servers. See the Manual for instructions.

        這樣實現是為了確保伺服器能夠正確處理從匿名事務更改為GTID事務的過程,此過程中可能同時包含這兩種模式的事務。在gtid_mode = on和gtid_mode = off之間切換時,GTID狀態(也就是gtid_executed的值)是持久化的,因此不管gtid_mode的型別如何更改,都可確保始終保留伺服器應用的GTID集。無論當前選擇的gtid_mode如何,與GTID相關的欄位都會顯示正確的資訊。顯示GTID集的欄位(例如replication_connection_status效能架構表中的gtid_executed,gtid_purged,RECEIVED_TRANSACTION_SET以及SHOW SLAVE STATUS的GTID相關結果)在沒有GTID時返回空字串。顯示單個GTID的欄位(如Performance Schema replication_applier_status_by_worker表中的CURRENT_TRANSACTION)在未使用GTID事務時顯示ANONYMOUS。從庫使用gtid_mode = on複製提供了自動定位的功能。


        當前選擇的gtid_mode也會影響gtid_next變數。下表顯示了伺服器對gtid_mode和gtid_next不同值的行為。每個條目的含義如下:


ANONYMOUS:生成匿名事務。

Error:生成錯誤並且無法執行SET GTID_NEXT。

UUID:NUMBER:使用指定的UUID:NUMBER生成GTID。

New GTID:使用自動生成的數字生成GTID。



        當二進位制日誌關閉且gtid_next設定為AUTOMATIC時,不會生成GTID,這與先前版本的行為一致。注意,為了保證主從資料一致性和例項恢復的效能,在MySQL 8中作為一項基本原則,除非有特殊需求,與複製相關的其它系統變數最好保持預設值,包括但不限於下面所列出的系統變數:


autocommit = ON

log_bin = ON

log_slave_updates = ON

innodb_flush_log_at_trx_commit = 1

sync_binlog = 1

master_info_repository = TABLE

relay_log_info_repository = TABLE

relay_log_recovery = OFF

binlog_gtid_simple_recovery = ON

innodb_replication_delay = 0

(3)用xtrabackup備份並傳輸


xtrabackup -uroot -p123456 --socket=/tmp/mysql.sock --no-lock --backup --compress --stream=xbstream --parallel=4 --target-dir=./ | ssh mysql@172.16.1.126 "xbstream -x -C /usr/local/mysql/data/ --decompress"

        使用xtrabackup的一個好處是,不必考慮從gtid_mode=off到gtid_mode=on的過程中是否存在正在進行的匿名事務。xtrabackup執行的是物理備份,主庫上無論是匿名事務還是GTID事務,最終資料檔案和二進位制日誌檔案都會被拷貝到從庫,並且在恢復備份、啟動例項和複製後,可以使用GTID的自動定位功能找到初始複製點。


(4)在從庫恢復備份


xtrabackup --prepare --target-dir=/usr/local/mysql/data/

(5)在從庫的配置檔案中新增以下選項


server_id=1126                 # 伺服器ID

read_only=on                   # 從庫只讀

gtid_mode=on                   # 開啟GTID

enforce-gtid-consistency=true  # 強制GTID一致

(6)啟動從庫


mysqld_safe --defaults-file=/etc/my.cnf &

(7)在從庫啟動複製


change master to

       master_host = '172.16.1.125',

       master_port = 3306,

       master_user = 'repl',

       master_password = '123456',

       master_auto_position = 1;

start slave;

show slave status\G

        可以在slave status中看到複製正在進行,Retrieved_Gtid_Set和Executed_Gtid_Set不斷增加,Seconds_Behind_Master逐漸縮小至0。


mysql> show slave status\G

*************************** 1. row ***************************

               Slave_IO_State: Waiting for master to send event

                  Master_Host: 172.16.1.125

                  Master_User: repl

                  Master_Port: 3306

                Connect_Retry: 60

              Master_Log_File: binlog.000008

          Read_Master_Log_Pos: 4013022

               Relay_Log_File: hdp3-relay-bin.000002

                Relay_Log_Pos: 638408

        Relay_Master_Log_File: binlog.000008

             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: 638469

              Relay_Log_Space: 4013168

              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: 52

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: 1125

                  Master_UUID: 8eed0f5b-6f9b-11e9-94a9-005056a57a4e

             Master_Info_File: mysql.slave_master_info

                    SQL_Delay: 0

          SQL_Remaining_Delay: NULL

      Slave_SQL_Running_State: waiting for handler commit

           Master_Retry_Count: 86400

                  Master_Bind: 

      Last_IO_Error_Timestamp: 

     Last_SQL_Error_Timestamp: 

               Master_SSL_Crl: 

           Master_SSL_Crlpath: 

           Retrieved_Gtid_Set: 8eed0f5b-6f9b-11e9-94a9-005056a57a4e:5283-19980

            Executed_Gtid_Set: 8eed0f5b-6f9b-11e9-94a9-005056a57a4e:1-7619

                Auto_Position: 1

         Replicate_Rewrite_DB: 

                 Channel_Name: 

           Master_TLS_Version: 

       Master_public_key_path: 

        Get_master_public_key: 0

            Network_Namespace: 

1 row in set (0.00 sec)

(8)將GTID引數新增到主庫的配置檔案中


gtid_mode=on

enforce-gtid-consistency=true

        至此完成聯機配置GTID複製。


2. 聯機更改複製模式

        如果已經在未開啟GITD的情況下配置了主從複製,可以聯機將複製模式修改為GTID以及自動定位。由於整個過程不需要停止MySQL例項,這種方式適合在生產環境中使用。開始前確保MySQL伺服器滿足以下前提條件:


複製拓撲中的所有伺服器都必須使用MySQL 5.7.6或更高版本。除非拓撲中的所有伺服器都使用此版本,否則無法在任何單個伺服器上聯機啟用GTID事務。

所有伺服器的gtid_mode預設設定為OFF。

        以下過程可以隨時暫停,之後再恢復,這使得該過程具有容錯能力。如果過程中出現任何不相關的錯誤,可以先暫停過程解決問題,然後再從停止的地方繼續。但至關重要的一點是,在繼續下一步之前必須完成之前的步驟。聯機改為GTID複製的步驟如下。


(1)在每臺伺服器上執行:


set global enforce_gtid_consistency=warn;

        保證所有操作都與GTID相容,並且確保錯誤日誌中沒有GTID的相關警告。


(2)在每臺伺服器上執行:


set global enforce_gtid_consistency=true;

(3)在每臺伺服器上執行:


set global gtid_mode=off_permissive;

        哪個伺服器首先執行此語句無關緊要,重要的是在開始下一步之前所有伺服器完成步驟。


(4)在每臺伺服器上執行:


set global gtid_mode=on_permissive;

(5)在每臺伺服器上,等待狀態變數ongoing_anonymous_transaction_count為0。可以使用以下方法檢查:


show status like 'ongoing_anonymous_transaction_count';

(6)如果二進位制日誌還用於複製以外的其它目的(如基於時間點的恢復等),需要在執行flush logs後備份二進位制日誌檔案。包含GTID事務的二進位制日誌在下一步執行之後無法使用。完成此步後,確保拓撲中的任何位置都不存在GTID事務。


(7)在每臺伺服器上執行:


set global gtid_mode=on;

(8)在每個從庫上執行以下操作:


stop slave;

change master to master_auto_position = 1;

start slave;

(9)在每臺伺服器上,將gtid-mode = on和enforce_gtid_consistency=true新增到my.cnf。


        現在可以保證所有事務都具有GTID(步驟5或更早生成的事務已經過處理),已經改為GTID複製模式。


        聯機將GTID事務複製改為匿名事務複製模式的過程基本是上述步驟的逆過程,唯一不同的是等待記錄事務複製的方式。


(1)在每個從庫上執行以下操作:


stop slave;

show slave status\G

change master to master_auto_position = 0, master_log_file = 'xxx', master_log_pos = xxx;

start slave;

        xxx可以從show slave status輸出的Master_Log_File和Read_Master_Log_Pos獲得。


(2)在每臺伺服器上執行:


set global gtid_mode=on_permissive;

(3)在每臺伺服器上執行:


set global gtid_mode=off_permissive;

(4)在每臺伺服器上,等待變數@@GLOBAL.GTID_OWNED等於空字串。可以使用以下方法檢查:


select @@global.gtid_owned;

        此時複製正常進行,但slave status中的Retrieved_Gtid_Set和Executed_Gtid_Set值不再變化。


(5)如果二進位制日誌還用於複製以外的其它目的(如基於時間點的恢復等),執行FLUSH LOGS後再備份二進位制日誌檔案。包含GTID事務的二進位制日誌在下一步執行之後無法使用。完成此步後,確保拓撲中的任何位置都不存在GTID事務。


(6)在每臺伺服器上執行:


set global gtid_mode=off;

(7)在每臺伺服器上執行:


set global enforce_gtid_consistency=false;

(8)在每臺伺服器上,在my.cnf中設定gtid-mode = off和enforce_gtid_consistency=false。


3. GTID相關係統變數

        前面已經在各個地方分散介紹過很多GTID相關的系統變數,如gtid_executed、gtid_next、gtid_purged、gtid_mode等,這裡對MySQL 8中的重要GTID系統變數加以簡單整理。


binlog_gtid_simple_recovery:布林型別全域性變數,控制MySQL啟動時從哪些binlog檔案中尋找GTID,預設值為ON。當binlog_gtid_simple_recovery=true時,初始化gtid_executed和gtid_purged值時只讀取最老和最新的binlog檔案。否則需要遍歷所有binlog檔案。

enforce_gtid_consistency:列舉型別全域性變數,指示是否強制GTID資料一致性,有效值為OFF、ON、WARN,預設值為OFF。

gtid_executed:全域性和會話級別都可以用,用來儲存已經執行過的GTID集合。

gtid_executed_compression_period:整型全域性變數,指示壓縮mysql.gtid_executed表之前允許的事務數,預設值為1000。使用二進位制日誌時該值不起作用,而是在每個二進位制日誌輪轉時壓縮mysql.gtid_executed表。

gtid_mode:列舉型別全域性變數,控制是否開啟GTID功能,有效值為OFF、OFF_PERMISSIVE、ON_PERMISSIVE、ON,預設值為OFF。聯機設定時,只能按順序一步步修改。

gtid_next:會話級列舉變數,用於指定是否以及如何獲取下一個GTID。有效值為AUTOMATIC、ANONYMOUS、UUID:NUMBER,預設值為AUTOMATIC。

gtid_owned:內部使用的只讀變數,指示當前正在使用的GTID以及擁有它的執行緒ID。

gtid_purged:全域性變數,設定已經執行但在binlog中被清除的GTID集合,是gtid_executed的子集。

二、GTID運維

        每個GTID唯一標識構成事務的一組二進位制日誌事件,在二進位制日誌中跟蹤GTID事務與其事件集之間的對映。應用連線到資料庫時,MySQL伺服器自動跳過之前已處理的GTID事務,此行為對於自動複製定位和正確的故障轉移至關重要。啟用GTID也給運維帶來了一些改變。


1. 跳過一個事務

        傳統基於二進位制座標的複製中,從庫由於某些錯誤導致複製中斷時,一個可能的解決方案是設定sql_slave_skip_counter全域性系統變數,跳過導致錯誤的事件,然後重啟複製。但啟用GTID後,執行的單位由事件變為事務,因此該方法不再有效(slave_skip_errors仍然可用),並會報以下錯誤。


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

mysql>

        從錯誤訊息可以看到,GTID跳過事務的方法是注入一個空事務,具體步驟為:

(1)定位出錯事務的GTID。

        從庫報錯我們需要獲得從庫執行的最後一個事務,方法有:

show slave status \G 中的 Executed_Gtid_Set。

show global variables like '%gtid%'; 中的 gtid_executed 。

show master status;中的Executed_Gtid_Set。


(2)將會話級系統變數gtid_next設定為上一步的GTID,如。


set gtid_next='8eed0f5b-6f9b-11e9-94a9-005056a57a4e:980058'

        注意gtid_next的值只能是單個GTID。


(3)注入空事務。


begin;commit;

(4)重啟複製。


set gtid_next='automatic';

start slave;

        重啟複製前需要將gtid_next設定為預設值'automatic'。下面是個跳過多個事務的例子。


stop slave;

set gtid_next='8eed0f5b-6f9b-11e9-94a9-005056a57a4e:980055';

begin;commit;

set gtid_next='8eed0f5b-6f9b-11e9-94a9-005056a57a4e:980056';

begin;commit;

set gtid_next='8eed0f5b-6f9b-11e9-94a9-005056a57a4e:980057';

begin;commit;

set gtid_next='automatic';

start slave;

2. mysqldump匯出

        使用mysqldump受set-gtid-purged選項影響,set-gtid-purged選項設定為AUTO(預設值)或ON時的輸出如下所示。


[mysql@hdp3~]$mysqldump --single-transaction --all-databases --master-data=2 --host=172.16.1.125 --user=repl --password=123456

-- MySQL dump 10.13  Distrib 8.0.16, for linux-glibc2.12 (x86_64)

--

-- Host: 172.16.1.125    Database:

-- ------------------------------------------------------

-- Server version       8.0.16

 

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;

/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;

/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;

 SET NAMES utf8mb4 ;

/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;

/*!40103 SET TIME_ZONE='+00:00' */;

/*!50606 SET @OLD_INNODB_STATS_AUTO_RECALC=@@INNODB_STATS_AUTO_RECALC */;

/*!50606 SET GLOBAL INNODB_STATS_AUTO_RECALC=OFF */;

/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;

/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;

/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;

/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

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=/*!80000 '+'*/ '8eed0f5b-6f9b-11e9-94a9-005056a57a4e:1-980059';

 

--

-- Position to start replication or point-in-time recovery from

--

 

-- CHANGE MASTER TO MASTER_LOG_FILE='binlog.000022', MASTER_LOG_POS=209837996;

SET @@SESSION.SQL_LOG_BIN = @MYSQLDUMP_TEMP_LOG_BIN;

 

...

 

-- Dump completed on 2019-06-13 10:36:35

[mysql@hdp3~]$

        開始部分的 SET @@SESSION.SQL_LOG_BIN= 0 防止匯入資料時基於本地伺服器生成新的GTID。接著GTID_PURGED被設定為備份時刻已經執行過的GTID事務,該操作將會初始化mysql.gtid_executed表、gtid_purge變數及gtid_executed變數。當mysqldump命令加入--set-gtid-purged=off選項時,則輸出中不會加入SQL_LOG_BIN= 0和GTID_PURGED的設定。如果要將資料匯入作為從庫初始化,不能設定--set-gtid-purged=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.

        細心的使用者到這裡可能心生疑問:為初始化從庫資料,命令列使用了--all-databases選項。mysql.gtid_executed表會不會被重建,進而通過GTID_PURGED設定的mysql.gtid_executed表會重新改變,重啟資料庫後讀取mysql.gtid_executed表可能獲得錯誤GTID集合導致複製錯誤?答案也在mysqldump的輸出中。


...

-- CHANGE MASTER TO MASTER_LOG_FILE='binlog.000022', MASTER_LOG_POS=209837996;

 

--

-- Current Database: `mysql`

--

 

CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysql` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */;

 

USE `mysql`;

...

        首先,如果從庫例項的mysql庫存在則不會刪除重建。


...

--

-- Table structure for table `gtid_executed`

--

 

/*!40101 SET @saved_cs_client     = @@character_set_client */;

 SET character_set_client = utf8mb4 ;

CREATE TABLE IF NOT EXISTS `gtid_executed` (

  `source_uuid` char(36) NOT NULL COMMENT 'uuid of the source where the transaction was originally executed.',

  `interval_start` bigint(20) NOT NULL COMMENT 'First number of interval.',

  `interval_end` bigint(20) NOT NULL COMMENT 'Last number of interval.',

  PRIMARY KEY (`source_uuid`,`interval_start`)

) /*!50100 TABLESPACE `mysql` */ ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

/*!40101 SET character_set_client = @saved_cs_client */;

 

--

-- Table structure for table `help_category`

--

...

        其次,如果mysql.gtid_executed表存在則不會刪除重建。最後,如果該表不存在則建立它,但不會向其裝載資料。由此得出結論,除非手工刪除了mysql.gtid_executed表,否則不會因它造成複製問題,至少MySQL 8是這樣。


3. 主從切換

        這裡分三種情況進行討論:從庫只讀、從庫讀寫並且有全部寫操作的二進位制日誌、從庫讀寫但寫操作的二進位制日誌不全。(1)從庫只讀

        這種情況從庫(新主庫)沒有做過本地的事務,只需執行正常切換。


-- 從庫(新主庫)

stop slave;

reset slave all;

 

-- 主庫(新從庫)

change master to

       master_host = '172.16.1.126',

       master_port = 3306,

       master_user = 'repl',

       master_password = '123456',

       master_auto_position = 1;

start slave;

        新主庫會生成自己的GTID事務,此時會出有兩個server_uuid對應的GTID:


mysql> select @@global.gtid_executed;

+-----------------------------------------------------------------------------------------+

| @@global.gtid_executed                                                                  |

+-----------------------------------------------------------------------------------------+

| 53442434-8bfa-11e9-bc15-005056a50f77:1-2,

8eed0f5b-6f9b-11e9-94a9-005056a57a4e:1-980059 |

+-----------------------------------------------------------------------------------------+

1 row in set (0.00 sec)

(2)從庫讀寫並且有全部寫操作的二進位制日誌


-- 從庫(新主庫)

drop table test.t1;

create table test.t1(a int);

insert into test.t1 select 100;

 

stop slave;

reset slave all;

 

-- 主庫(新從庫)

change master to

       master_host = '172.16.1.125',

       master_port = 3306,

       master_user = 'repl',

       master_password = '123456',

       master_auto_position = 1;

start slave;

        此時在show slave status的輸出中可以看到:


Retrieved_Gtid_Set: 8eed0f5b-6f9b-11e9-94a9-005056a57a4e:980060-980062

 Executed_Gtid_Set: 53442434-8bfa-11e9-bc15-005056a50f77:1-2, 8eed0f5b-6f9b-11e9-94a9-005056a57a4e:1-980062

        剛才從庫執行的三個本地事務,在新從庫上正常複製。因為本地事務與複製事務GTID的server_uuid部分不同,只要binlog保留完整,從庫上的寫操作在主從切換後可以自動複製到新的從庫上,與匿名複製相比明顯方便許多。(3)從庫讀寫但寫操作的二進位制日誌不全


-- 從庫(新主庫)

drop table test.t1;

create table test.t1(a int);

insert into test.t1 select 100;

 

stop slave;

reset slave all;

flush logs;

 

# 模擬binlog檔案丟失

mv binlog.000022 binlog.000022.bak

 

-- 主庫(新從庫)

change master to

       master_host = '172.16.1.125',

       master_port = 3306,

       master_user = 'repl',

       master_password = '123456',

       master_auto_position = 1;

start slave;

        此時在show slave status的輸出中報錯如下:


Last_IO_Errno: 13114

Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'Could not open log file'

        真實環境要是遇到這種情況還是重建從庫吧。二進位制日誌檔案預設的保留時間是30天(binlog_expire_logs_seconds = 2592000)。一般來說從庫的寫操作通常是為保留一些報表結果或臨時資料,這些操作的最早時間很大可能已超過三十天,在這之後進行主從切換就會出現問題。這也是建議從庫readonly的原因之一。如果確實要做比如加索引等不影響資料的操作可以在執行前設定sql_log_bin變數:


set sql_log_bin=0;

create index idx1 on test.t1(a);

        這樣不會增加本地GTID。但還是要強調,從庫最好始終readonly。


三、GTID限制

涉及非事務儲存引擎的更新。使用GTID時,一條語句或一個事務中,不能對非事務性儲存引擎(如MyISAM)表和事務儲存引擎(如InnoDB)的表一起更新,因為這種混合引擎同時更新可能導致將多個GTID分配給同一事務。下面兩組命令都會報同樣的錯誤。

use test;

create table t_myisam(a int) engine=myisam;

create table t_innodb(a int) engine=innodb;

update t_myisam, t_innodb set t_myisam.a=1, t_innodb.a=1;

 

begin;

insert into t_myisam select 1;

insert into t_innodb select 1;

update t_myisam set a=2;

update t_innodb set a=2;

commit;

        錯誤資訊:


ERROR 1785 (HY000): Statement violates GTID consistency: 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.

        在MySQL 8中,這個限制並沒有多大影響,因為包括系統表在內都是InnoDB表,預設已經沒有myisam表了,除非使用者建表時顯示定義。


CREATE TABLE ... SELECT語句。 CREATE TABLE ...使用基於GTID的複製時不允許使用SELECT語句。當binlog_format設定為STATEMENT時,CREATE TABLE ... SELECT語句作為一個具有單一GTID的事務記錄在二進位制日誌中。但如果使用ROW格式,則該語句將記錄為具有兩個GTID的兩個事務。如果主伺服器使用STATEMENT格式而從伺服器使用ROW格式,則從伺服器將無法正確處理事務,因此GTID不允許使用CREATE TABLE ... SELECT語句來防止出現這種情況。

mysql> show variables like 'binlog_format';

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| binlog_format | ROW   |

+---------------+-------+

1 row in set (0.00 sec)

 

mysql> create table t2 as select * from t1;

ERROR 1786 (HY000): Statement violates GTID consistency: CREATE TABLE ... SELECT.

mysql> set binlog_format=statement;

Query OK, 0 rows affected (0.00 sec)

 

mysql> create table t2 as select * from t1;

ERROR 1786 (HY000): Statement violates GTID consistency: CREATE TABLE ... SELECT.

mysql>

臨時表。當binlog_format設定為STATEMENT,伺服器上啟用GTID時,不能在事務、過程、函式或觸發器內使用CREATE TEMPORARY TABLE和DROP TEMPORARY TABLE語句。如果設定了autocommit = 1,則可以在使用GTID時在這些上下文之外使用它們。從MySQL 8.0.13開始,當binlog_format設定為ROW或MIXED時且啟用GTID時,允許在事務、過程、函式或觸發器內使用CREATE TEMPORARY TABLE和DROP TEMPORARY TABLE語句。這些語句不會寫入二進位制日誌,因此不會複製到從庫。

mysql> show variables like 'binlog_format';

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| binlog_format | ROW   |

+---------------+-------+

1 row in set (0.01 sec)

 

mysql> begin;

Query OK, 0 rows affected (0.00 sec)

 

mysql> create temporary table tmp1 select * from t1;

Query OK, 1 row affected (0.00 sec)

Records: 1  Duplicates: 0  Warnings: 0

 

mysql> commit;

Query OK, 0 rows affected (0.00 sec)

 

mysql> set binlog_format=statement;

ERROR 3745 (HY000): Changing @@session.binlog_format is disallowed when the session has open temporary table(s). You could wait until these temporary table(s) are dropped and try again.

mysql> drop temporary table tmp1;

Query OK, 0 rows affected (0.00 sec)

 

mysql> set binlog_format=statement;

Query OK, 0 rows affected (0.00 sec)

 

mysql> create temporary table tmp1 select * from t1;

Query OK, 1 row affected (0.00 sec)

Records: 1  Duplicates: 0  Warnings: 0

 

mysql> drop temporary table tmp1;

Query OK, 0 rows affected (0.00 sec)

 

mysql> begin;

Query OK, 0 rows affected (0.00 sec)

 

mysql> create temporary table tmp1 select * from t1;

ERROR 3748 (HY000): Statement violates GTID consistency: CREATE TEMPORARY TABLE and DROP TEMPORARY TABLE are not allowed inside a transaction or inside a procedure in a transactional context when @@session.binlog_format=STATEMENT.

mysql>

        要防止執行會導致基於GTID的複製失敗的語句,必須在啟用GTID時使用--enforce-gtid-consistency選項啟動所有伺服器。這會導致前面討論的語句失敗並顯示錯誤。


忽略伺服器。使用GTID時,不推薦使用CHANGE MASTER TO語句的IGNORE_SERVER_IDS選項,因為已經應用的事務會自動被忽略。在啟動基於GTID的複製之前,需要檢查並清除(CHANGE MASTER TO IGNORE_SERVER_IDS = ();)之前在相關伺服器上設定的所有忽略的伺服器ID列表。可以為各個通道發出的SHOW SLAVE STATUS語句顯示被忽略的伺服器ID列表(如果有)。如果沒有則Replicate_Ignore_Server_Ids欄位為空。

GTID模式和mysqldump。可以將使用mysqldump建立的轉儲匯入到啟用了GTID模式的MySQL伺服器中,前提是目標伺服器的二進位制日誌中沒有重疊的GTID。

[mysql@hdp3/usr/local/mysql/data]$mysqldump --single-transaction --all-databases --master-data=2 --host=172.16.1.125 --user=wxy --password=123456 | mysql -uroot -p123456

mysql: [Warning] Using a password on the command line interface can be insecure.

mysqldump: [Warning] Using a password on the command line interface can be insecure.

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. 

ERROR 3546 (HY000) at line 26: @@GLOBAL.GTID_PURGED cannot be changed: the added gtid set must not overlap with @@GLOBAL.GTID_EXECUTED

mysqldump: Got errno 0 on write

[mysql@hdp3/usr/local/mysql/data]$mysql -uroot -p123456 -e "reset master;"

mysql: [Warning] Using a password on the command line interface can be insecure.

[mysql@hdp3/usr/local/mysql/data]$mysqldump --single-transaction --all-databases --master-data=2 --host=172.16.1.125 --user=wxy --password=123456 | mysql -uroot -p123456

mysql: [Warning] Using a password on the command line interface can be insecure.

mysqldump: [Warning] Using a password on the command line interface can be insecure.

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. 

[mysql@hdp3/usr/local/mysql/data]$

四、GTID集合運算函式

1. GTID內建函式

        MySQL 8包含GTID_SUBSET、GTID_SUBTRACT、WAIT_FOR_EXECUTED_GTID_SET、WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS 4個內建函式,用於GTID集合的基本運算。


GTID_SUBSET(set1,set2):給定兩個GTID集set1和set2,set1是set2的子集返回true,否則返回false。

mysql> select gtid_subset('','') c1,

    ->        gtid_subset('53442434-8bfa-11e9-bc15-005056a50f77:1','53442434-8bfa-11e9-bc15-005056a50f77:1') c2,

    ->        gtid_subset('53442434-8bfa-11e9-bc15-005056a50f77:1','53442434-8bfa-11e9-bc15-005056a50f77:1-10') c3,

    ->        gtid_subset('53442434-8bfa-11e9-bc15-005056a50f77:1','53442434-8bfa-11e9-bc15-005056a50f77:2-10') c4,

    ->        gtid_subset('53442434-8bfa-11e9-bc15-005056a50f77:1-2','53442434-8bfa-11e9-bc15-005056a50f77:1') c5,

    ->        gtid_subset('53442434-8bfa-11e9-bc15-005056a50f77:1-2','53442434-8bfa-11e9-bc15-005056a50f77:1-10') c6,

    ->        gtid_subset('53442434-8bfa-11e9-bc15-005056a50f77:1-2','53442434-8bfa-11e9-bc15-005056a50f77:2-10') c7,

    ->        gtid_subset('53442434-8bfa-11e9-bc15-005056a50f77:1-2','8eed0f5b-6f9b-11e9-94a9-005056a57a4e:1-2') c8,

    ->        gtid_subset('53442434-8bfa-11e9-bc15-005056a50f77:1-2','8eed0f5b-6f9b-11e9-94a9-005056a57a4e:1-2,53442434-8bfa-11e9-bc15-005056a50f77:1-2') c9;

+----+----+----+----+----+----+----+----+----+

| c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c9 |

+----+----+----+----+----+----+----+----+----+

|  1 |  1 |  1 |  0 |  0 |  1 |  0 |  0 |  1 |

+----+----+----+----+----+----+----+----+----+

1 row in set (0.00 sec)

GTID_SUBTRACT(set1,set2):給定兩個GTID集set1和set2,僅返回set1與set2的差集。

mysql> select gtid_subtract('','') c1,

    ->        gtid_subtract('53442434-8bfa-11e9-bc15-005056a50f77:1','53442434-8bfa-11e9-bc15-005056a50f77:1') c2,

    ->        gtid_subtract('53442434-8bfa-11e9-bc15-005056a50f77:1','53442434-8bfa-11e9-bc15-005056a50f77:1-10') c3,

    ->        gtid_subtract('53442434-8bfa-11e9-bc15-005056a50f77:1','53442434-8bfa-11e9-bc15-005056a50f77:2-10') c4,

    ->        gtid_subtract('53442434-8bfa-11e9-bc15-005056a50f77:1-2','53442434-8bfa-11e9-bc15-005056a50f77:1') c5,

    ->        gtid_subtract('53442434-8bfa-11e9-bc15-005056a50f77:1-2','53442434-8bfa-11e9-bc15-005056a50f77:1-10') c6,

    ->        gtid_subtract('53442434-8bfa-11e9-bc15-005056a50f77:1-2','53442434-8bfa-11e9-bc15-005056a50f77:2-10') c7,

    ->        gtid_subtract('53442434-8bfa-11e9-bc15-005056a50f77:1-5','53442434-8bfa-11e9-bc15-005056a50f77:3-10') c8,

    ->        gtid_subtract('53442434-8bfa-11e9-bc15-005056a50f77:1-2,8eed0f5b-6f9b-11e9-94a9-005056a57a4e:1-2','8eed0f5b-6f9b-11e9-94a9-005056a57a4e:2-3') c9\G

*************************** 1. row ***************************

c1: 

c2: 

c3: 

c4: 53442434-8bfa-11e9-bc15-005056a50f77:1

c5: 53442434-8bfa-11e9-bc15-005056a50f77:2

c6: 

c7: 53442434-8bfa-11e9-bc15-005056a50f77:1

c8: 53442434-8bfa-11e9-bc15-005056a50f77:1-2

c9: 53442434-8bfa-11e9-bc15-005056a50f77:1-2,

8eed0f5b-6f9b-11e9-94a9-005056a57a4e:1

1 row in set (0.00 sec)

WAIT_FOR_EXECUTED_GTID_SET(gtid_set[, timeout]):等到伺服器應用了包含在gtid_set中的所有事務。如果指定可選的timeout值(秒數),超時會使函式停止等待而退出。

mysql> select wait_for_executed_gtid_set('53442434-8bfa-11e9-bc15-005056a50f77:1');

+----------------------------------------------------------------------+

| wait_for_executed_gtid_set('53442434-8bfa-11e9-bc15-005056a50f77:1') |

+----------------------------------------------------------------------+

|                                                                    0 |

+----------------------------------------------------------------------+

1 row in set (0.00 sec)

mysql> select wait_for_executed_gtid_set('53442434-8bfa-11e9-bc15-005056a50f77:1-7');

+------------------------------------------------------------------------+

| wait_for_executed_gtid_set('53442434-8bfa-11e9-bc15-005056a50f77:1-7') |

+------------------------------------------------------------------------+

|                                                                      0 |

+------------------------------------------------------------------------+

1 row in set (0.00 sec)

mysql> select wait_for_executed_gtid_set('53442434-8bfa-11e9-bc15-005056a50f77:8',5);

+------------------------------------------------------------------------+

| wait_for_executed_gtid_set('53442434-8bfa-11e9-bc15-005056a50f77:8',5) |

+------------------------------------------------------------------------+

|                                                                      1 |

+------------------------------------------------------------------------+

1 row in set (5.00 sec)

WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS(gtid_set[, timeout][,channel]):與WAIT_FOR_EXECUTED_GTID_SET類似,但針對單個啟動的複製通道。

mysql> select wait_until_sql_thread_after_gtids('53442434-8bfa-11e9-bc15-005056a50f77:1');

+-----------------------------------------------------------------------------+

| wait_until_sql_thread_after_gtids('53442434-8bfa-11e9-bc15-005056a50f77:1') |

+-----------------------------------------------------------------------------+

|                                                                           0 |

+-----------------------------------------------------------------------------+

1 row in set (0.00 sec)

mysql> select wait_until_sql_thread_after_gtids('53442434-8bfa-11e9-bc15-005056a50f77:1-7');

+-------------------------------------------------------------------------------+

| wait_until_sql_thread_after_gtids('53442434-8bfa-11e9-bc15-005056a50f77:1-7') |

+-------------------------------------------------------------------------------+

|                                                                             0 |

+-------------------------------------------------------------------------------+

1 row in set (0.00 sec)

mysql> select wait_until_sql_thread_after_gtids('53442434-8bfa-11e9-bc15-005056a50f77:8',5);

+-------------------------------------------------------------------------------+

| wait_until_sql_thread_after_gtids('53442434-8bfa-11e9-bc15-005056a50f77:8',5) |

+-------------------------------------------------------------------------------+

|                                                                            -1 |

+-------------------------------------------------------------------------------+

1 row in set (5.00 sec)

2. 使用者自定義函式

        使用者可以在自定義函式中呼叫這些內建函式,實現一些常用的GTID集合運算,下面是MySQL 8文件中的幾個例子。


如果兩個GTID集相同,函式返回非零值。

create function gtid_is_equal(gtid_set_1 longtext, gtid_set_2 longtext)

returns int deterministic

  return gtid_subset(gtid_set_1, gtid_set_2) and gtid_subset(gtid_set_2, gtid_set_1);

 


如果兩個GTID集不相交,函式返回非零值。

create function gtid_is_disjoint(gtid_set_1 longtext, gtid_set_2 longtext)

returns int deterministic

  return gtid_subset(gtid_set_1, gtid_subtract(gtid_set_1, gtid_set_2));

如果兩個GTID集不相交,則函式返回非零,sum是兩個集的並集。

create function gtid_is_disjoint_union(gtid_set_1 longtext, gtid_set_2 longtext, sum longtext)

returns int deterministic

  return gtid_is_equal(gtid_subtract(sum, gtid_set_1), gtid_set_2) and

         gtid_is_equal(gtid_subtract(sum, gtid_set_2), gtid_set_1);

函式返回格式化的GTID集。沒有空格且沒有重複,UUID按字母順序排列,間隔按數字順序排列。

create function gtid_normalize(g longtext)

returns longtext deterministic

return gtid_subtract(g, '');

函式返回兩個GTID集的並集。

create function gtid_union(gtid_set_1 longtext, gtid_set_2 longtext)

returns longtext deterministic

  return gtid_normalize(concat(gtid_set_1, ',', gtid_set_2));

函式返回兩個GTID集的交集。

create function gtid_intersection(gtid_set_1 longtext, gtid_set_2 longtext)

returns longtext deterministic

  return gtid_subtract(gtid_set_1, gtid_subtract(gtid_set_1, gtid_set_2));

函式返回兩個GTID集的對稱差集。

create function gtid_symmetric_difference(gtid_set_1 longtext, gtid_set_2 longtext)

returns longtext deterministic

  return gtid_subtract(concat(gtid_set_1, ',', gtid_set_2), gtid_intersection(gtid_set_1, gtid_set_2));

函式返回除去指定UUID的GTID集。

create function gtid_subtract_uuid(gtid_set longtext, uuid text)

returns longtext deterministic

  return gtid_subtract(gtid_set, concat(uuid, ':1-', (1 << 63) - 2));

函式返回指定UUID的GTID集。

create function gtid_intersection_with_uuid(gtid_set longtext, uuid text)

returns longtext deterministic

  return gtid_subtract(gtid_set, gtid_subtract_uuid(gtid_set, uuid));

3. 使用示例

(1)驗證從庫的複製是否最新

        內建函式GTID_SUBSET和GTID_SUBTRACT可用於檢查從庫是應用了主庫的每個事務。使用GTID_SUBSET執行此檢查,在從庫上執行以下命令:


master_gtid_executed=`mysql -uwxy -p123456 -h172.16.1.125 -N -e "select replace(@@global.gtid_executed,char(10),'')"` 

slave_gtid_executed=`mysql -uwxy -p123456 -N -e "select replace(@@global.gtid_executed,char(10),'')"` 

sql="select gtid_subset('$master_gtid_executed', '$slave_gtid_executed')"

mysql -uwxy -p123456 -e "$sql"

        如果返回0則master_gtid_executed中的某些GTID不存在於slave_gtid_executed中,因此從庫不是最新的。要使用GTID_SUBTRACT執行檢查,請在從庫上執行以下命令:


master_gtid_executed=`mysql -uwxy -p123456 -h172.16.1.125 -N -e "select replace(@@global.gtid_executed,char(10),'')"` 

slave_gtid_executed=`mysql -uwxy -p123456 -N -e "select replace(@@global.gtid_executed,char(10),'')"` 

sql="select gtid_subtract('$master_gtid_executed', '$slave_gtid_executed')"

mysql -uwxy -p123456 -e "$sql"

        返回master_gtid_executed中但未在slave_gtid_executed中的GTID。如果返回值不為空,則從庫不是最新的。


(2)驗證mysqldump匯出匯入

        自定義函式GTID_IS_EQUAL、GTID_IS_DISJOINT和GTID_IS_DISJOINT_UNION可用於驗證涉及多個資料庫和伺服器的備份和還原操作。此示例中,server1包含資料庫db1,server2包含資料庫db2。目標是將資料庫db2複製到server1,server1上的結果應該是兩個資料庫的並集。過程是使用mysqldump備份server2,然後在server1上恢復此備份。


        如果mysqldump的選項--set-gtid-purged設定為ON或預設值為AUTO,則程式的輸出包含SET @@GLOBAL.gtid_purged語句,該語句將server2中的gtid_executed集新增到server1上的gtid_purged集。gtid_purged集包含已在伺服器上提交但在伺服器上的任何二進位制日誌檔案中不存在的所有事務的GTID。將資料庫db2複製到server1時,必須將server2上提交的事務的GTID(不在server1上的二進位制日誌檔案中)新增到server1的gtid_purged集中以使該集完成。


使用GTID_IS_EQUAL驗證備份操作是否為SET @@GLOBAL.gtid_purged語句計算了正確的GTID集。在server2上,從mysqldump輸出中提取該語句,並將GTID集儲存到本地變數中,例如$gtid_purged_set。然後執行以下語句:

server2> SELECT GTID_IS_EQUAL($gtid_purged_set, @@GLOBAL.gtid_executed);

        如果結果為1,則兩個GTID集相等,並且已正確計算該集。


使用GTID_IS_DISJOINT驗證mysqldump輸出中設定的GTID與server1上的gtid_executed集不重疊。如果存在任何重疊,則在將資料庫db2複製到server1時會出現錯誤。將輸出中的gtid_purged集提取並儲存到如上所述的區域性變數中,然後執行以下語句:

server1> SELECT GTID_IS_DISJOINT($gtid_purged_set, @@GLOBAL.gtid_executed);

        如果結果為1,則兩個GTID集之間沒有重疊,因此不存在重複的GTID。


使用GTID_IS_DISJOINT_UNION驗證還原操作是否導致server1上的GTID狀態正確。在恢復備份之前,在server1上,通過執行以下語句獲取現有的gtid_executed集:

server1> SELECT @@GLOBAL.gtid_executed;

        將結果儲存在本地變數$original_gtid_executed中。還將gtid_purged集儲存在區域性變數中。當server2的備份已恢復到server1上時,執行以下語句以驗證GTID狀態:


server1> SELECT GTID_IS_DISJOINT_UNION($original_gtid_executed, 

                                       $gtid_purged_set, 

                                       @@GLOBAL.gtid_executed);

        如果結果為1,則儲存的函式已驗證來自server1的原始gtid_executed集($original_gtid_executed)和從server2新增的gtid_purged集($gtid_purged_set)沒有重疊,並且server1上已更新的gtid_executed集現在包含來自server1的前一個gtid_executed集加上來自server2的gtid_purged集,這是所需的結果。確保在server1上進行任何進一步的事務之前執行此檢查,否則gtid_executed集中的新事務將會失敗。


(3)手工選擇作為新主庫的從庫

        自定義函式GTID_UNION可用於從一組複製從庫中識別最新的從庫,以便在主庫意外停止後執行手動切換。如果某些從庫遇到複製延遲,則此函式可用於計算最新的從庫,而無需等待所有從庫應用完其現有的中繼日誌,從而最大限度地縮短主從切換時間。該函式可以返回每個從庫上的gtid_executed集合與從庫接收的事務集合的並集,後者記錄在performance_schema.replication_connection_status表中。可以比較這些結果,以查詢哪個從庫的事務記錄是最新的,即使並非所有交易都已提交。


        在每個複製從屬伺服器上,通過發出以下語句來計算完整的事務記錄:


SELECT GTID_UNION(RECEIVED_TRANSACTION_SET, @@GLOBAL.gtid_executed) 

    FROM performance_schema.replication_connection_status 

    WHERE channel_name = 'name';

        然後比較每個從庫的結果,選擇具有最新事務記錄的從庫用作新主庫。


(4)檢查從庫上的異常事務

        自定義函式GTID_SUBTRACT_UUID可用於檢查從庫是否只接收到源自其指定主庫的事務。對於單主複製,執行以下語句,server_uuid_of_master是主庫的server_uuid:


SELECT GTID_SUBTRACT_UUID(@@GLOBAL.gtid_executed, server_uuid_of_master);

        如果結果不為空,則返回的事務是不是源自指定主庫的異常事務。對於多主複製拓撲中的從庫,重複該功能,例如:


SELECT GTID_SUBTRACT_UUID(GTID_SUBTRACT_UUID(@@GLOBAL.gtid_executed,

                                             server_uuid_of_master_1),

                                             server_uuid_of_master_2);

        如果結果不為空,則返回的事務是來自非指定主庫的異常事務。


(5)驗證複製拓撲中的伺服器是否執行過本地事務

        自定義函式GTID_INTERSECTION_WITH_UUID可用於驗證伺服器是否執行過本地事務。可以在伺服器上發出以下語句來檢查:


SELECT GTID_INTERSECTION_WITH_UUID(@@GLOBAL.gtid_executed, my_server_uuid);

(6)在多主複製設定中驗證附加從庫

        假設master1和master2為雙主複製,互為主從,同時master2還有自己的從庫slave3,如下圖所示。


MySQL 8 複製(五)——配置GTID複製


        如果master2配置了log_slave_updates = ON,slave3也將接收並應用master1的事務,如果master2使用log_slave_updates = OFF,則不會這樣做。在這種情況下,自定義函式GTID_INTERSECTION_WITH_UUID可用於標識master2發起的事務,丟棄master2從master1複製的事務。然後可以使用內建函式GTID_SUBSET將結果與slave3上的gtid_executed集進行比較。如果slave3與master2保持同步,則slave3上的gtid_executed設定包含交集中的所有事務(源自master2的事務)。


        要執行此檢查,可將master2的gtid_executed、master2的server_uuid和slave3的gtid_executed集儲存到客戶端變數中,例如:


    $master2_gtid_executed :=

      master2> SELECT @@GLOBAL.gtid_executed;

    $master2_server_uuid :=

      master2> SELECT @@GLOBAL.server_uuid;

    $slave_gtid_executed :=

      slave3> SELECT @@GLOBAL.gtid_executed;

        然後使用GTID_INTERSECTION_WITH_UUID和GTID_SUBSET將這些變數作為輸入,例如在slave3上執行:


SELECT GTID_SUBSET(GTID_INTERSECTION_WITH_UUID($master2_gtid_executed,

                                               $master2_server_uuid),

                                               $slave_gtid_executed);

        來自master2的伺服器識別符號($master2_server_uuid)與GTID_INTERSECTION_WITH_UUID一起使用,以識別並返回源自master2的gtid_executed集合中的那些GTID,省略源自master1的那些GTID。然後使用GTID_SUBSET將得到的GTID集與從庫上所有已執行GTID的集合進行比較。如果此語句返回非零(true),則來自master2的所有已識別的GTID(第一個集輸入)也位於從庫的gtid_executed集(第二個集輸入)中,這意味著從庫已複製源自master2的所有事務。

————————————————

版權宣告:本文為CSDN博主「wzy0623」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連結及本宣告。

原文連結:

https://blog.csdn.net/wzy0623/article/details/91982743








About Me

........................................................................................................................

● 本文作者:小麥苗,部分內容整理自網路,若有侵權請聯絡小麥苗刪除

● 本文在itpub、部落格園、CSDN和個人微 信公眾號( xiaomaimiaolhr)上有同步更新

● 本文itpub地址: http://blog.itpub.net/26736162

● 本文部落格園地址: http://www.cnblogs.com/lhrbest

● 本文CSDN地址: https://blog.csdn.net/lihuarongaini

● 本文pdf版、個人簡介及小麥苗雲盤地址: http://blog.itpub.net/26736162/viewspace-1624453/

● 資料庫筆試面試題庫及解答: http://blog.itpub.net/26736162/viewspace-2134706/

● DBA寶典今日頭條號地址: http://www.toutiao.com/c/user/6401772890/#mid=1564638659405826

........................................................................................................................

● QQ群號: 230161599 、618766405

● 微 信群:可加我微 信,我拉大家進群,非誠勿擾

● 聯絡我請加QQ好友 646634621 ,註明新增緣由

● 於 2020-02-01 06:00 ~ 2020-02-31 24:00 在西安完成

● 最新修改時間:2020-02-01 06:00 ~ 2020-02-31 24:00

● 文章內容來源於小麥苗的學習筆記,部分整理自網路,若有侵權或不當之處還請諒解

● 版權所有,歡迎分享本文,轉載請保留出處

........................................................................................................................

小麥苗的微店https://weidian.com/s/793741433?wfr=c&ifr=shopdetail

小麥苗出版的資料庫類叢書http://blog.itpub.net/26736162/viewspace-2142121/

小麥苗OCP、OCM、高可用網路班http://blog.itpub.net/26736162/viewspace-2148098/

小麥苗騰訊課堂主頁https://lhr.ke.qq.com/

........................................................................................................................

使用 微 信客戶端掃描下面的二維碼來關注小麥苗的微 信公眾號( xiaomaimiaolhr)及QQ群(DBA寶典)、新增小麥苗微 信, 學習最實用的資料庫技術。

........................................................................................................................

歡迎與我聯絡

 

 



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

相關文章