首页 > 数据库 >MySQL基于GTID复制模式小结

MySQL基于GTID复制模式小结

时间:2022-12-21 10:33:20浏览次数:43  
标签:binlog slave MySQL master GTID mysql 小结 gtid

一、GTID概念介绍

GTID是mysql5.6版本出来的新特性

GTID即全局事务ID (global transaction identifier), 其保证为每一个在主上提交的事务在复制集群中可以生成一个唯一的ID。mysql主从结构在一主一从情况下对于GTID来说就没有优势了,而对于2台主以上的结构优势异常明显,可以在数据不丢失的情况下切换新主。

使用GTID需要注意: 在构建主从复制之前,在一台将成为主的实例上进行一些操作(如数据清理等),通过GTID复制,这些在主从成立之前的操作也会被复制到从服务器上,引起复制失败。也就是说通过GTID复制都是从最先开始的事务日志开始,即使这些操作在复制之前执行。比如在server1上执行一些drop、delete的清理操作,接着在server2上执行change的操作,会使得server2也进行server1的清理操作。

GTID实际上是由UUID+TID (即transactionId)组成的。其中UUID(即server_uuid) 产生于auto.conf文件(cat /iddbs/mysql/data/auto.cnf),是一个MySQL实例的唯一标识。TID代表了该实例上已经提交的事务数量,并且随着事务提交单调递增,所以GTID能够保证每个MySQL实例事务的执行(不会重复执行同一个事务,并且会补全没有执行的事务)。GTID在一组复制中,全局唯一。 下面是一个GTID的具体形式 :

mysql> select @@server_uuid;

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

| @@server_uuid                        |

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

| 09d4c484-afc6-11eb-a6fd-000c293bb7d1 |

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

 

 

mysql> show master status;

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

| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                                                                       |

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

| mysql_bin.000012 |      236 |              |                  | 09d4c484-afc6-11eb-a6fd-000c293bb7d1:1-2,

f9e37b40-a26e-11eb-9b22-000c293bb7d1:1-990216 |

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

 

GTID:09d4c484-afc6-11eb-a6fd-000c293bb7d1:1-2

UUID:09d4c484-afc6-11eb-a6fd-000c293bb7d1

transactionId: 1-2

 

在整个复制架构中GTID 是不变化的,即使在多个连环主从中也不会变。

例如:ServerA --->ServerB ---->ServerC

GTID从在ServerA ,ServerB,ServerC 中都是一样的

了解了GTID的格式,通过uuid就能刚确认事务在哪个实例上提交的。通过GTID可以既方便的进行复制结构上的故障转移,新主设置,可以很好解决如下图所示的问题:

 

如果是传统的基于binlog file 和pos的主从复制, 如图, Server1(Master)崩溃,根据从上show slave status获得Master_log_File/Read_Master_Log_Pos的值,Server2(Slave)已经跟上了主,Server3(Slave)没有跟上主。这时要是把Server2提升为主,Server3变成Server2的从。这时在Server3上执行change的时候需要做一些计算。如果使用GTID就非常简单, 由于同一事务的GTID在所有节点上的值一致,那么根据Server3当前停止点的GTID就能定位到Server2上的GTID。甚至由于MASTER_AUTO_POSITION功能的出现,都不需要知道GTID的具体值,直接使用CHANGE MASTER TO MASTER_HOST='xxx', MASTER_USER='XXX',MASTER_PASSWORD='XXX',MASTER_AUTO_POSITION=1 ;命令就可以直接完成failover的工作

二、GTID和binlog的关系

1、GTID在binlog中的结构

 

2、GTID event 结构

 

-  Previous_gtid_log_event

Previous_gtid_log_event 在每个binlog 头部都会有每次binlog rotate的时候存储在binlog头部Previous-GTIDs在binlog中只会存储在这台机器上执行过的所有binlog,不包括手动设置gtid_purged值。换句话说,如果你手动set global gtid_purged=xx; 那么xx是不会记录在Previous_gtid_log_event中的。

-  GTID和Binlog之间的关系是怎么对应的呢? 如何才能找到GTID=? 对应的binlog文件呢?

假设有4个binlog: bin.001,bin.002,bin.003,bin.004

bin.001 : Previous-GTIDs=empty; binlog_event有: 1-40

bin.002 : Previous-GTIDs=1-40; binlog_event有: 41-80

bin.003 : Previous-GTIDs=1-80; binlog_event有: 81-120

bin.004 : Previous-GTIDs=1-120; binlog_event有: 121-160

假设现在我们要找GTID=$A,那么MySQL的扫描顺序为:

- 从最后一个binlog开始扫描(即: bin.004)

- bin.004的Previous-GTIDs=1-120,如果$A=140 > Previous-GTIDs,那么肯定在bin.004中

- bin.004的Previous-GTIDs=1-120,如果$A=88 包含在Previous-GTIDs中,那么继续对比上一个binlog文件 bin.003,然后再循环前面2个步骤,直到找到为止.

 

三、GTID重要参数持久化

1、GTID相关参数

参数

commet

gtid_executed

执行过的所有GTID

gtid_purged

丢弃掉的GTID

gtid_mode

gitd模式

gtid_next

session级别的变量,下一个gtid

gtid_owned

正在运行的gtid

enforce_gtid_consistency

保证GTID安全的参数

这里简单说下几个常用参数的作用:

gtid_executed

在当前实例上执行过的 GTID 集合,实际上包含了所有记录到 binlog 中的事务。设置 set sql_log_bin=0 后执行的事务不会生成 binlog 事件,也不会被记录到 gtid_executed 中。执行 RESET MASTER 可以将该变量置空。

gtid_purged

binlog 不可能永远驻留在服务上,需要定期进行清理(通过 expire_logs_days 可以控制定期清理间隔),否则迟早它会把磁盘用尽。gtid_purged 用于记录本机上已经执行过,但是已经被清除了的 binlog 事务集合。它是 gtid_executed 的子集。只有 gtid_executed 为空时才能手动设置该变量,此时会同时更新 gtid_executed 为和 gtid_purged 相同的值。

gtid_executed 为空意味着要么之前没有启动过基于 GTID 的复制,要么执行过 RESET MASTER。执行 RESET MASTER 时同样也会把 gtid_purged 置空,即始终保持 gtid_purged 是 gtid_executed 的子集

gtid_next

会话级变量,指示如何产生下一个GTID。可能的取值如下:

-  AUTOMATIC: 自动生成下一个 GTID,实现上是分配一个当前实例上尚未执行过的序号最小的 GTID。

-  ANONYMOUS: 设置后执行事务不会产生GTID。

-  显式指定的GTID: 可以指定任意形式合法的 GTID 值,但不能是当前 gtid_executed 中的已经包含的 GTID,否则下次执行事务时会报错。

2、重要参数如何持久化

1) 如何持久化gtid_executed    (前提是log-bin=mysql-bin, log_slave_update=1 )

gtid_executed = mysql.gtid_executed        #正常情况下  

select * from mysql.gtid_executed;   #可查询

或者

gtid_executed = mysql.gtid_executed + last_binlog中最后没写到mysql.gtid_executed中的gtid_event     #恢复情况下

2)如何持久化重置的gtid_purged值?

reset master; set global gtid_purged=$A:a-b;

================================================================================================

1. 由于有可能手动设置过gtid_purged=$A:a-b, binlog.index中,last_binlog的Previous-GTIDs并不会包含$A:a-b

2. 由于有可能手动设置过gtid_purged=$A:a-b, binlog.index中,first_binlog的Previous-GTIDs肯定不会出现$A:a-b

3. 重置的gtid_purged = @@global.gtid_executed(mysql.gtid_executed:注意,考虑到这个表的更新触发条件,所以这里

   用@@global.gtid_executed代替) - last_binlog的Previous-GTIDs  - last_binlog所有的gtid_event

4. 下面就用 $reset_gtid_purged 来表示重置的gtid

3) 如何持久化gtid_purged  (前提是log-bin=mysql-bin, log_slave_update=1 )

gtid_purged=binlog.index:first_binlog的Previous-GTIDs + $reset_gtid_purged

四、开启GTID的必要条件

-  MySQL 5.6 版本,在my.cnf文件中添加:

gtid_mode=on (必选)                    #开启gtid功能

log_bin=log-bin=mysql-bin (必选)       #开启binlog二进制日志功能

log-slave-updates=1 (必选)             #也可以将1写为on

enforce-gtid-consistency=1 (必选)      #也可以将1写为on

-  MySQL 5.7或更高版本,在my.cnf文件中添加:

gtid_mode=on    (必选)

enforce-gtid-consistency=1  (必选)

log_bin=mysql-bin           (可选)    #高可用切换,最好开启该功能

log-slave-updates=1     (可选)       #高可用切换,最好打开该功能

 

特意说下"log_slave_updates"这个参数选项,通常slave服务器从master服务器接收到的更新不记入slave的二进制日志。该参数选项告诉slave从服务器将其SQL线程执行的更新记入到slave服务器自己的二进制日志。为了使该选项生效,还必须启动binlog二进制日志功能!!比如:

A01和A02为主主复制,A01和B01为主从复制,在测试的过程中发现了以下问题:

-  A01和A02的主主复制是没有问题的(从A01写入数据能同步到A02,从A02写入数据能够同步到A01);

-  主从同步的时候,当从A01写入的时候,数据可以写入到B01;

-  当从A02写入的时候,数据就不能写入到B01;

这个问题产生的原因:log_slave_updates参数的状态为NO

 

五、GTID的工作原理

从服务器连接到主服务器之后,把自己执行过的GTID (Executed_Gtid_Set: 即已经执行的事务编码)<SQL线程> 、获取到的GTID (Retrieved_Gtid_Set: 即从库已经接收到主库的事务编号) <IO线程>发给主服务器,主服务器把从服务器缺少的GTID及对应的transactions发过去补全即可。当主服务器挂掉的时候,找出同步最成功的那台从服务器,直接把它提升为主即可。如果硬要指定某一台不是最新的从服务器提升为主, 先change到同步最成功的那台从服务器, 等把GTID全部补全了,就可以把它提升为主了。

GTID是MySQL 5.6的新特性,可简化MySQL的主从切换以及Failover。GTID用于在binlog中唯一标识一个事务。当事务提交时,MySQL Server在写binlog的时候,会先写一个特殊的Binlog Event,类型为GTID_Event,指定下一个事务的GTID,然后再写事务的Binlog。主从同步时GTID_Event和事务的Binlog都会传递到从库,从库在执行的时候也是用同样的GTID写binlog,这样主从同步以后,就可通过GTID确定从库同步到的位置了。也就是说,无论是级联情况,还是一主多从情况,都可以通过GTID自动找点儿,而无需像之前那样通过File_name和File_position找点儿了。

简而言之,GTID的工作流程为:

-  master更新数据时,会在事务前产生GTID,一同记录到binlog日志中。

-  slave端的i/o 线程将变更的binlog,写入到本地的relay log中。

-  sql线程从relay log中获取GTID,然后对比slave端的binlog是否有记录。

-  如果有记录,说明该GTID的事务已经执行,slave会忽略。

-  如果没有记录,slave就会从relay log中执行该GTID的事务,并记录到binlog。

-  在解析过程中会判断是否有主键,如果没有就用二级索引,如果没有就用全部扫描。

六、GTID的优缺点

GTID的优点

-  一个事务对应一个唯一ID,一个GTID在一个服务器上只会执行一次;

-  GTID是用来代替传统复制的方法,GTID复制与普通复制模式的最大不同就是不需要指定二进制文件名和位置;

-  减少手工干预和降低服务故障时间,当主机挂了之后通过软件从众多的备机中提升一台备机为主机;

 

GTID复制是怎么实现自动同步,自动对应位置的呢?

比如这样一个主从架构:ServerC <-----ServerA ----> ServerB

即一个主数据库ServerA,两个从数据库ServerB和ServerC

当主机ServerA 挂了之后 ,此时ServerB执行完了所有从ServerA 传过来的事务,ServerC 延时一点。这个时候需要把 ServerB 提升为主机 ,Server C 继续为备机;当ServerC 链接ServerB 之后,首先在自己的二进制文件中找到从ServerA 传过来的最新的GTID,然后将这个GTID 发送到ServerB ,ServerB 获得这个GTID之后,就开始从这个GTID的下一个GTID开始发送事务给ServerC。这种自我寻找复制位置的模式减少事务丢失的可能性以及故障恢复的时间。

GTID的缺点(限制)

-  不支持非事务引擎;

-  不支持create table ... select 语句复制(主库直接报错);(原理: 会生成两个sql, 一个是DDL创建表SQL, 一个是insert into 插入数据的sql; 由于DDL会导致自动提交, 所以这个sql至少需要两个GTID, 但是GTID模式下, 只能给这个sql生成一个GTID)

-  不允许一个SQL同时更新一个事务引擎表和非事务引擎表;

-  在一个复制组中,必须要求统一开启GTID或者是关闭GTID;

-  开启GTID后,就不再使用原来的传统复制方式;

-  不支持sql_slave_skip_counter;

 

七、到底为啥要用GTID?

1. classic replication         [传统复制 , 运维之痛]

 

  1. GTID replication       [GTID复制,很简单]

 

八、基本运维

创建mysql三个实例server1(3308)、server2(3308)、server3(3308),主从架构:Server2<-----Server1 ----> Server3启动之后,执行change时需要注意

1、搭建GTID,并配置主从关系(server1为主,server2为从)

#####   前提:server1、server2、server3配置文件中关于GTID的配置已完成,mysql服务并启动  ######

 

登录三台server均执行如下操作:

mysql> set sql_log_bin=0;

mysql> alter user root@'localhost' identified by 'root';

mysql> set sql_log_bin=1;

 

server1执行:

mysql> set sql_log_bin=0;

mysql> create user rep@'%' identified with mysql_native_password by 'rep';

mysql> grant replication slave on *.* to rep@'%';

mysql> flush privileges;

mysql> set sql_log_bin=1;

 

server2执行:

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

mysql> start slave;

mysql> show slave status\G;

 

server3执行:

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

mysql> start slave;

mysql> show slave status\G;

2、测试复制的故障转移

server1(3308)挂了,服务器起不来了。需要把其中的一个从设置为主,另一个设置为其的从库:

server2(3308):

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='192.168.221.141',master_user='rep',master_password='rep',master_port=3308,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

1) 从服务器跳过一个错误的事务

mysql> stop slave;

 

mysql> set session gtid_next='4e659069-3cd8-11e5-9a49-001c4270714e:5';     #在session里设置gtid_next,即跳过这个GTID

 

mysql> begin;      #开启一个空事务

mysql> commit;

 

mysql> SET SESSION GTID_NEXT = AUTOMATIC;   #把gtid_next设置回来

 

mysql> start slave;  #开启复制

 

在此成功跳过了错误,同步继续。可以通过这个办法来处理复制失败的问题,这里还有个例子(从服务器中跳过一条语句/事务),比如主库无意间删除了某张表,利用重复延迟复制保留数据

#########  server2 从库操作  ##############

mysql > stop slave;

Query OK, 0 ROWS affected (0.05 sec)

mysql > CHANGE master TO MASTER_DELAY=600;   ##设置主从延迟同步的时间(是延迟加载relay_log),单位为秒

Query OK, 0 ROWS affected (0.27 sec)

mysql > START slave;

Query OK, 0 ROWS affected, 1 warning (0.06 sec)

 

#######    server1 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, 当然此时主从的数据已经不一致了。

注意:通过GTID的复制都是没有指定MASTER_LOG_FILE和MASTER_LOG_POS的,所以通过GTID复制都是从最先开始的事务开始,除非在自己的binlog里面有执行过之前的记录,才会继续后面的执行

 

2)通过server2从库去恢复server3从库(在上面的基础之上进行操作)

#####  server3 上查看t2表   #############3

mysql> select * from t2;

Empty set (0.00 sec)

 

因为server1执行了truncate t2表,server3复制server1的操作   

mysql> stop slave;   ##数据丢失,停止复制

mysql> reset master;  ##在还原数据之前,一定要清空GTID

 

##########  server2上进行数据备份 #########

[root@db141 ~]# mysqldump -uroot -proot -S data3308/my3308.sock  --single-transaction --master-data=2  --set-gtid-purged=ON  -A>all.sql;

[root@db141 ~]# vim all.sql

 

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 '+'*/ '09d4c484-afc6-11eb-a6fd-000c293bb7d1:1-15,

c26609a0-c442-11eb-babf-000c29d84243:1';

 

注意:在备份的时候设置了--set-gtid-purged=ON(默认就是ON),则在数据恢复的时候,即 server3是不会写入bin-log日志的。但是会执行gtid语句,而且这些gtid语句的uuid是备份这数据数据库的uuid;

 

 

#####  server3恢复数据#####

mysql> source  /root/all.sql;

mysql> show master status;

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

| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                                                                 |

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

| mysql_bin.000001 |      152 |              |                  | 09d4c484-afc6-11eb-a6fd-000c293bb7d1:1-15,

c26609a0-c442-11eb-babf-000c29d84243:1 |

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

1 row in set (0.00 sec)

 

mysql> start slave;

 

如果server2在数据备份的时候,命令如下:

[root@db141 ~]# mysqldump -uroot -proot -S data3308/my3308.sock  --single-transaction --master-data=2  --set-gtid-purged=OFF -A>all.sql;

设置了--set-gtid-purged=OFF,则在数据恢复的时候,即 server3是会写入到binlog日志中的,执行的gtid语句的uuid则是server3自己的uuid;

mysql> source  /root/all.sql;

mysql> show master status;

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

| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                          |

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

| mysql_bin.000001 |  1191825 |              |                  | adf717ab-c4d4-11eb-ae0a-000c29ba607f:1-149 |

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

1 row in set (0.00 sec)

 

 

mysql> select @@server_uuid;

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

| @@server_uuid                        |

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

| adf717ab-c4d4-11eb-ae0a-000c29ba607f |

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

 

 

3) 事务日志被purge ,再change

server1上有一批操作,并有日志被purge,server2再去change,注意此时server2的gtid_executed为空

######   server1 操作##################

mysql> show binary logs;

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

| Log_name         | File_size | Encrypted |

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

| mysql_bin.000001 |       156 | No        |

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

1 row in set (0.00 sec)

 

 

mysql> show master status;

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

| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |

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

| mysql_bin.000001 |      156 |              |                  |                   |

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

1 row in set (0.00 sec)

 

mysql> select * from t2;

+----+

| id |

+----+

|  1 |

+----+

1 row in set (0.01 sec)

 

 

mysql> insert into t2 values(2);

Query OK, 1 row affected (0.00 sec)

 

 

mysql> insert into t2 values(3);

Query OK, 1 row affected (0.00 sec)

 

 

mysql> show binary logs;

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

| Log_name         | File_size | Encrypted |

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

| mysql_bin.000001 |       710 | No        |

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

1 row in set (0.00 sec)

 

 

mysql> flush logs;

Query OK, 0 rows affected (0.03 sec)

 

 

mysql> insert into t2 values(4);

Query OK, 1 row affected (0.00 sec)

 

 

mysql> insert into t2 values(5);

Query OK, 1 row affected (0.01 sec)

 

 

mysql> insert into t2 values(6);

Query OK, 1 row affected (0.01 sec)

 

 

mysql> flush logs;

Query OK, 0 rows affected (0.03 sec)

 

 

mysql> insert into t2 values(7);

Query OK, 1 row affected (0.00 sec)

 

 

mysql> insert into t2 values(8);

Query OK, 1 row affected (0.00 sec)

 

mysql> show master status;

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

| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                        |

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

| mysql_bin.000003 |      750 |              |                  | 09d4c484-afc6-11eb-a6fd-000c293bb7d1:1-7 |

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

1 row in set (0.00 sec)

 

 

mysql> show binary logs;

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

| Log_name         | File_size | Encrypted |

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

| mysql_bin.000001 |       757 | No        |

| mysql_bin.000002 |      1074 | No        |

| mysql_bin.000003 |       750 | No        |

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

 

mysql> show variables like '%gtid%';

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

| Variable_name                    | Value                                    |

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

| binlog_gtid_simple_recovery      | ON                                       |

| enforce_gtid_consistency         | ON                                       |

| gtid_executed                    | 09d4c484-afc6-11eb-a6fd-000c293bb7d1:1-7 |

| gtid_executed_compression_period | 0                                        |

| gtid_mode                        | ON                                       |

| gtid_next                        | AUTOMATIC                                |

| gtid_owned                       |                                          |

| gtid_purged                      |                                          |

| session_track_gtids              | OFF                                      |

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

 

mysql> purge binary logs to 'mysql_bin.000003';   #日志被purge之后剩下的binlog

Query OK, 0 rows affected (0.00 sec)

 

 

mysql> show variables like '%gtid%';

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

| Variable_name                    | Value                                    |

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

| binlog_gtid_simple_recovery      | ON                                       |

| enforce_gtid_consistency         | ON                                       |

| gtid_executed                    | 09d4c484-afc6-11eb-a6fd-000c293bb7d1:1-7 |

| gtid_executed_compression_period | 0                                        |

| gtid_mode                        | ON                                       |

| gtid_next                        | AUTOMATIC                                |

| gtid_owned                       |                                          |

| gtid_purged                      | 09d4c484-afc6-11eb-a6fd-000c293bb7d1:1-5 |

| session_track_gtids              | OFF                                      |

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

9 rows in set (0.00 sec)

 

 

mysql> show binary logs;

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

| Log_name         | File_size | Encrypted |

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

| mysql_bin.000003 |       750 | No        |

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

1 row in set (0.00 sec)

 

######   server2   change操作################

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

Query OK, 0 rows affected, 8 warnings (0.03 sec)

 

 

mysql> start slave;

Query OK, 0 rows affected, 1 warning (0.01 sec)

 

 

mysql> show slave status\G;

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

               Slave_IO_State:

                  Master_Host: 192.168.221.140

                  Master_User: rep

                  Master_Port: 3308

                Connect_Retry: 60

              Master_Log_File:

          Read_Master_Log_Pos: 4

               Relay_Log_File: relay_bin.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:

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

Master_SSL_Verify_Server_Cert: No

                Last_IO_Errno: 13114

                Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'Cannot replicate because the master purged required binary logs. Replicate the missing transactions from elsewhere, or provision a new slave from backup. Consider increasing the master's binary log expiration period. The GTID set sent by the slave is '', and the missing transactions are '09d4c484-afc6-11eb-a6fd-000c293bb7d1:1-5''

               Last_SQL_Errno: 0

               Last_SQL_Error:

  Replicate_Ignore_Server_Ids:

 

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

mysql> stop slave;

mysql> set global gtid_purged ='09d4c484-afc6-11eb-a6fd-000c293bb7d1:1-5';   #只有gtid_executed为空的时候,才能手动设置gtid_purged

mysql> start slave;

mysql> show variables like '%gtid%';

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

| Variable_name                    | Value                                    |

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

| binlog_gtid_simple_recovery      | ON                                       |

| enforce_gtid_consistency         | ON                                       |

| gtid_executed                    | 09d4c484-afc6-11eb-a6fd-000c293bb7d1:1-5 |

| gtid_executed_compression_period | 0                                        |

| gtid_mode                        | ON                                       |

| gtid_next                        | AUTOMATIC                                |

| gtid_owned                       |                                          |

| gtid_purged                      | 09d4c484-afc6-11eb-a6fd-000c293bb7d1:1-5 |

| session_track_gtids              | OFF                                      |

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

9 rows in set (0.00 sec)

 

mysql> show slave status\G;

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

               Slave_IO_State: Waiting for master to send event

                  Master_Host: 192.168.221.140

                  Master_User: rep

                  Master_Port: 3308

                Connect_Retry: 60

              Master_Log_File: mysql_bin.000003

          Read_Master_Log_Pos: 750

               Relay_Log_File: relay_bin.000002

                Relay_Log_Pos: 363

        Relay_Master_Log_File: mysql_bin.000003

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

                   Last_Error: Coordinator stopped because there were error(s) in the worker(s). The most recent failure being: Worker 1 failed executing transaction '09d4c484-afc6-11eb-a6fd-000c293bb7d1:6' at master log mysql_bin.000003, end_log_pos 442. See error log and/or performance_schema.replication_applier_status_by_worker table for more details about this failure or others, if any.

 

 

4 如何从classic  replication 升级为GTID replication

-  offline 方式升级 (线下升级)

offline 的方式升级最简单:

- 全部关闭mysql

- 在my.cnf文件中配置好GTID

- 重启mysql

- 登录mysql,执行"change master to MASTER_AUTO_POSITION=1;"

-  online 方式升级 (线上升级)

先介绍几个重要GTID_MODE的参数:

GTID_MODE = OFF

不产生Normal_GTID,只接受来自master的ANONYMOUS_GTID

GTID_MODE = OFF_PERMISSIVE

不产生Normal_GTID,可以接受来自master的ANONYMOUS_GTID & Normal_GTID

GTID_MODE = ON_PERMISSIVE

产生Normal_GTID,可以接受来自master的ANONYMOUS_GTID & Normal_GTID

GTID_MODE = ON

产生Normal_GTID,只接受来自master的Normal_GTID

归纳总结:

1)当master产生Normal_GTID的时候,如果slave的gtid_mode(OFF)不能接受Normal_GTID,那么就会报错

2)当master产生ANONYMOUS_GTID的时候,如果slave的gtid_mode(ON)不能接受ANONYMOUS_GTID,那么就会报错

3)设置auto_position的条件: 当master的gtid_mode=ON时,slave可以为OFF_PERMISSIVE,ON_PERMISSIVE,ON。

   除此之外,都不能设置auto_position = on

============================================

下面开始说下如何online 升级为GTID模式?

step 1: 每台server执行

检查错误日志,直到没有错误出现,才能进行下一步

mysql> SET @@GLOBAL.ENFORCE_GTID_CONSISTENCY = WARN;

step 2: 每台server执行

mysql> SET @@GLOBAL.ENFORCE_GTID_CONSISTENCY = ON;

step 3: 每台server执行

不用关心一组复制集群的server的执行顺序,只需要保证每个Server都执行了,才能进行下一步

mysql> SET @@GLOBAL.GTID_MODE = OFF_PERMISSIVE;

step 4: 每台server执行

不用关心一组复制集群的server的执行顺序,只需要保证每个Server都执行了,才能进行下一步

mysql> SET @@GLOBAL.GTID_MODE = ON_PERMISSIVE;

step 5: 在每台server上执行,如果ONGOING_ANONYMOUS_TRANSACTION_COUNT=0就可以

不需要一直为0,只要出现过0一次,就ok

mysql> SHOW STATUS LIKE 'ONGOING_ANONYMOUS_TRANSACTION_COUNT';

step 6: 确保所有anonymous事务传递到slave上了

#master上执行

mysql> SHOW MASTER STATUS;

#每个slave上执行

mysql> SELECT MASTER_POS_WAIT(file, position);

或者,等一段时间,只要不是大的延迟,一般都没问题

step 7: 每台Server上执行

mysql> SET @@GLOBAL.GTID_MODE = ON;

step 8: 在每台server上将my.cnf中添加好gtid配置

gtid_mode=on

enforce-gtid-consistency=1

log_bin=mysql-bin

log-slave-updates=1

step 9: 在从机上通过change master语句进行复制

mysql> STOP SLAVE;

mysql> CHANGE MASTER TO MASTER_AUTO_POSITION = 1;

mysql> START SLAVE;

 

 

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

前提:

```
基于binlog日志已搭建好主从关系,29:3306和29:3307互为主从关系
```

1、从传统复制模式切换为GTID复制模式

```bash
# 在主从库上同时修改参数enforce_gtid_consistency=warn,确保error log中不会出现警告信息,如# # 果有,需要先修复,再继续
mysql> set global enforce_gtid_consistency=warn;
# 在主从服务器上把enforce_gtid_consistency修改为on,保障GTID的一致性
mysql> set global enforce_gtid_consistency=on;
# 在主从服务器上同时调整GTID模式为off_permissive
mysql> set global gtid_mode=off_permissive;
# 在主从服务器上同时调整GTID模式为on_permissive
mysql> set global gtid_mode=on_permissive;
# 确认冲库的ongoing_anonymous_transaction_count的参数是否为0,如果为0,意味着没有等待的事务,可以直接进行下一步
mysql> show global status like 'ongoing_anonymous_%';
+-------------------------------------+-------+
| Variable_name | Value |
+-------------------------------------+-------+
| Ongoing_anonymous_transaction_count | 0 |
+-------------------------------------+-------+
1 row in set (0.00 sec)
# 在主从库上同时设置gtid_mode为开启状态
mysql> set global gtid_mode=on;
mysql> show variables like '%gtid%';
+----------------------------------+-----------+
| Variable_name | Value |
+----------------------------------+-----------+
| binlog_gtid_simple_recovery | ON |
| enforce_gtid_consistency | ON |
| gtid_executed_compression_period | 1000 |
| gtid_mode | ON |
| gtid_next | AUTOMATIC |
| gtid_owned | |
| gtid_purged | |
| session_track_gtids | OFF |
+----------------------------------+-----------+
# 把传统复制模式改为GTID复制,先把原有的传统复制停掉stop slave,在执行change master to master_auto_position=1,再启动slave
# 更改29:3307的配置
mysql> stop slave;

mysql> change master to master_auto_position=1;

mysql> start slave;
# 测试在主库29:3306添加一条数据
mysql> insert into test04.t4 values(1,'tt','cd');
# 在从库29:3307验证
mysql> show slave status\G;
Retrieved_Gtid_Set: 22346d12-9a6a-11ea-bd3c-fa163e25e077:1
Executed_Gtid_Set: 22346d12-9a6a-11ea-bd3c-fa163e25e077:1
Auto_Position: 1
# 从传统的binlog日志复制转变为gtid复制模式成功

# 更改29:3306的配置
mysql> stop slave;
mysql> change master to master_auto_position=1;
mysql> start slave;
ERROR 1872 (HY000): Slave failed to initialize relay log info structure from the repository
# 报错原因启动slave时,使用repository中信息初始化relay log结构失败了,解决方法如下:
mysql> reset slave;
mysql> start slave;
# 测试在29:3307添加一条数据
mysql> insert into test04.t4 values(5,'uu','ff');
# 在29:3306上验证
mysql> show slave status\G;
Retrieved_Gtid_Set: 5fcfeb62-9b29-11ea-8018-fa163e25e077:1
Executed_Gtid_Set: 22346d12-9a6a-11ea-bd3c-fa163e25e077:1,
5fcfeb62-9b29-11ea-8018-fa163e25e077:1
```

2、从GTID复制模式切换为传统复制模式的过程

```bash
# 思路:先在从库中执行stop slave,停掉主从复制,然后调整为传统复制模式,让master_auto_position=0

# 在29:3307和29:3306同时执行
mysql> stop slave;
Query OK, 0 rows affected (0.00 sec)

# 29:3306上执行
mysql> change master to master_auto_position=0,master_host="192.168.1.29", master_port=3307,master_user="yaya",master_password="123456",\
-> master_log_file="mysql-bin.000037", master_log_pos=680;
Query OK, 0 rows affected, 2 warnings (0.07 sec)

# 29:3307上执行
mysql> change master to master_auto_position=0,master_host="192.168.1.29", master_port=3306, master_user="yaya",master_password="123456", \
-> master_log_file="mysql-bin.000051", master_log_pos=680;
# 3306和3307开启复制功能
mysql> start slave;
Query OK, 0 rows affected (0.08 sec)
# 3306和3307服务器上同时调整GTID模式为
mysql> set global gtid_mode=on_permissive;
# 3306和3307服务器上同时调整GTID模式
mysql> set global gtid_mode=off_permissive;
# 3306和3307服务器上同时关闭GTID功能
mysql> set global enforce_gtid_consistency=off;
mysql> set global gtid_mode=off;

注意: 如果在配置文件中配置过gtid_mode和enforce_gtid_consistency两个参数,记得更改配置文件,下次重启服务后直接生效

# 测试,分别在3306和3307上分别插入数据,查看是否同步成功,并用show slave status\G;查看以下参数是否发生改变
Retrieved_Gtid_Set:
Executed_Gtid_Set: 22346d12-9a6a-11ea-bd3c-fa163e25e077:1-2,
5fcfeb62-9b29-11ea-8018-fa163e25e077:1-2
Auto_Position: 0
# gtid的值未增加,并且Auto_Position为0,说明切换成功

标签:binlog,slave,MySQL,master,GTID,mysql,小结,gtid
From: https://www.cnblogs.com/harda/p/16995694.html

相关文章

  • 基于Spring+SpringMVC+Mybatis+Mysql在线考试系统
    @目录一、系统介绍二、功能展示1.用户登陆2.学生页面3.考试信息(老师)4.试卷库(老师)5.试题库(老师)6.考生信息(老师)7.成绩分析(老师)8.成绩排名(老师)9.错题统计(老师)10.成绩导出(老......
  • Mysql用户及其权限
    一、创建用户createuser'user_name'identifiedby'password';二、用户授权grant[权限名]on数据库名.表名touser_name[withoptiongrant];三、查看数据库中......
  • 基于Springboot+Mybatis+mysql+vue考研规划与交流系统
    @目录一、系统介绍二、功能展示1.主页(普通用户)2.登陆、注册(普通用户)3.复习规划制定(普通用户)4.经验分享交流(普通用户)5.考研学校资讯(普通用户)6.我的文章(普通用户)7.个人信......
  • Navicate for Mysql 中文免费版安装
    1.下载NavicatforMySQ中文破解版链接:https://pan.baidu.com/s/1fG5RfyEsOuyua5yi4Zt-fA提取码:36022.解压压缩包得到两个文件navicat111_mysql_cs_x64.exe、Patch......
  • 使用otter实现数据同步——mysql、oracle的数据同步利器
    文章目录Otter⽬前⽀持了什么整体架构环境准备下载安装修改配置⽂件运⾏ManagerNode配置⼀个同步任务添加canal添加数据源添加数据表配置添加⼀个chan......
  • MySQL Threads Running
    1、 广电告警背景如下: 主机:xxxx:3306,MySQL运行的Thread大于30,请关注,2021-07-1515:30:002、猜测是因为业务量造成?3、mysqlthreadrunning的理解  每秒查询次数(Qu......
  • MySQL8.0—clone plugin
    1、MySQL8.0cloneplugin简介 1) 克隆插件允许从本地或远程的MySQLServer中克隆数据。克隆的数据是存储在InnoDB中的schema(database)、table(表)、tablespaces(表空间)和d......
  • MySQL中这14个牛逼的功能,惊艳到我了!!!
    前言我最近几年用MYSQL数据库挺多的,发现了一些非常有用的小玩意,今天拿出来分享到大家,希望对你会有所帮助。1.group_concat在我们平常的工作中,使用groupby进行分组的场......
  • MySQL——数据库锁
    一、锁的定义?锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除传统的计算资源(如CPU、RAM、I/O等)的争用以外,数据也是一种供许多用户共享的资源。如何......
  • MySQL
    MySQL运算符本章节我们主要介绍MySQL的运算符及运算符的优先级。MySQL主要有以下几种运算符:算术运算符比较运算符逻辑运算符位运算符算术运算符MySQL支持的算术运算......