前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >线上的一次GTID搭建MySQL主从操作

线上的一次GTID搭建MySQL主从操作

作者头像
AsiaYe
发布2019-11-06 17:41:16
7790
发布2019-11-06 17:41:16
举报
文章被收录于专栏:DBA随笔DBA随笔

//

线上的一次GTID搭建MySQL主从操作

//

前两天同事说了线上的一个小问题,就是某一套环境的复制用户和其他的不统一,因为一直有事儿,这个问题就一直没有解决,今天早上来到公司,想要解决这个问题,结果遇到了一点儿小波折,这里记录一下,算是再积累一点关于GTID的经验吧。

先对环境做个介绍:

主库的IP是XX.XX.XXX.161

从库的IP是XX.XX.XXX.171

复制的模式是GTID模式

复制用户是repluser

端口是4308

关于GTID的概念,之前已经介绍过很多次了,这里不再赘述,有兴趣的可以看看文章分类一栏中关于GTID的介绍,我们只看看下面这三个参数的含义:

gtid_purged:这个是当前已经丢弃的gtid的值

gtid_executed:这个是当前已经执行过的gtid的值

gtid_nexe:下一个要执行的gtid的值

今天我们主要来看这个案例。我们的目的很明确,就是修改复制用户,首先在从库上查看复制用户:

mysql--dba_admin@127.0.0.1:(none) 10:27:26>>show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: XX.XX.XXX.161
                  Master_User: repluser
                  Master_Port: 4308
                Connect_Retry: 60
              Master_Log_File: mysqlbin.000003
          Read_Master_Log_Pos: 113372207
               Relay_Log_File: slave-relay-bin.000008
                Relay_Log_Pos: 46431
        Relay_Master_Log_File: mysqlbin.000003
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

可以看到,复制的用户是repluser,我们需要将它改为dba_repl,所做的操作如下:

1、首先我们执行stop slave命令,断开主从之间的复制关系。此时记录从库收到的gtid的值和已经执行的gtid的值。

           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: d9f94d88-463a-11e9-b424-005056b72c2a:19-360195
            Executed_Gtid_Set: 6f4936a0-463b-11e9-a324-005056b7ed6e:1-26,
d9f94d88-463a-11e9-b424-005056b72c2a:143504-360195
                Auto_Position: 0
         Replicate_Rewrite_DB: 
                 Channel_Name: 
           Master_TLS_Version: 

可以看到这里从库的execute的gtid的值有两个,分别是:

6f4936a0-463b-11e9-a324-005056b7ed6e:1-26,

d9f94d88-463a-11e9-b424-005056b72c2a:143504-360195

也就是说,从库执行过的事务的gtid有存在于两个服务器上,很明显,之前从库上面进行过一些操作,这里提醒大家,如果不想在从库上出现多个gtid,需要在从库上设置read_only的选项。

再来看看retrieved_gtid_set的值,这个值是从库上当前收到的gtid的值,是:

d9f94d88-463a-11e9-b424-005056b72c2a:19-360195

2、然后我们把从库的gtid_purged的值设置成为已经执行过的gtid_executed值,告诉从库,这些gtid的事务已经执行完了。也就是

d9f94d88-463a-11e9-b424-005056b72c2a:143504-360195

使用的操作过程如下:

mysql--dba_admin@127.0.0.1 >>reset slave all;
Query OK, 0 rows affected (0.00 sec)
mysql--dba_admin@127.0.0.1 >>set global gtid_purged='d9f94d88-463a-11e9-b424-005056b72c2a:143504-360195';
ERROR 1840 (HY000): @@GLOBAL.GTID_PURGED can only be set when @@GLOBAL.GTID_EXECUTED is empty.

可以看到,当我们直接进行修改的时候,提示我们需要将从库的gtid_executed的值置为空,才能进行重置,这里我们使用reset master的语句将gtid_executed置为空,如下:

mysql--dba_admin@127.0.0.1 >>reset master;
Query OK, 0 rows affected (0.02 sec)
mysql--dba_admin@127.0.0.1 >>set global gtid_purged='d9f94d88-463a-11e9-b424-005056b72c2a:143504-360195';
Query OK, 0 rows affected (0.00 sec)

可以看到,我们reset master之后,可以对gtid_purged进行设置了。

3、有了上一步的基础之后,从库已经了解了事务号在

143504-360195之间的事务已经被执行完了,所以从库在执行事务的时候会自动跳过这个区间的。此时我们开启主从复制:

mysql--dba_admin@127.0.0.1 >>change master to master_host='XX.XX.XXX.161',
    -> master_user='dba_repl',
    -> master_password='XXXXXXXX',
    -> master_port=4308,
    -> master_auto_position=1;
Query OK, 0 rows affected, 1 warning (0.01 sec)

mysql--dba_admin@127.0.0.1 >>start slave;
Query OK, 0 rows affected (0.00 sec)

查看复制关系,可以看到报了这样一个错误:

       Relay_Master_Log_File: mysqlbin.000002
            Slave_IO_Running: Yes
           Slave_SQL_Running: No
             Replicate_Do_DB: 
                  Last_Error: Coordinator stopped because there were error(s)
 in the worker(s). The most recent failure being: Worker 0 
failed executing transaction 'd9f94d88-463a-11e9-b424-005056b72c2a:1'
 at master log mysqlbin.000002, end_log_pos 734. See error log and/or
 performance_schema.replication_applier_status_by_worker table for
 more details about this failure or others, if any.

我们可以观察到IO线程是正常的,而SQL线程是错误的,报错是'd9f94d88-463a-11e9-b424-005056b72c2a:1'事务无法被从库顺利执行。

此时我们查看从库上的gtid相关的参数的值:

          Master_SSL_Crlpath: 
          Retrieved_Gtid_Set: d9f94d88-463a-11e9-b424-005056b72c2a:1-143503:360196-360321
           Executed_Gtid_Set: d9f94d88-463a-11e9-b424-005056b72c2a:143504-360195
               Auto_Position: 1
        Replicate_Rewrite_DB: 

可以看到,从库收到的gtid的值变为了:

d9f94d88-463a-11e9-b424-005056b72c2a:

1-143503:360196-360321

而之前是:

d9f94d88-463a-11e9-b424-005056b72c2a:

19-360195

很明显,目前这个值是不对的,我们想要的是收到的gtid的值是从360195开始的事务id,但是从库却收到了编号为1的事务id,也就是说,多收到了gtid编号为1-143503的事务id,这是我们不想要的。

4、手动设置一下从库的gtid_next的值,让它强行从

d9f94d88-463a-11e9-b424-005056b72c2a:360196开始,看看效果:

mysql--dba_admin@127.0.0.1 >>set session gtid_next='d9f94d88-463a-11e9-b424-005056b72c2a:360196';
Query OK, 0 rows affected (0.00 sec)

mysql--dba_admin@127.0.0.1 >>start slave;
Query OK, 0 rows affected (0.01 sec)

mysql--dba_admin@127.0.0.1 >>show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: XX.XX.XXX.161
                  Master_User: dba_repl
                  Master_Port: 4308
                Connect_Retry: 60
              Master_Log_File: mysqlbin.000003
          Read_Master_Log_Pos: 113446772
               Relay_Log_File: slave-relay-bin.000002
                Relay_Log_Pos: 365
        Relay_Master_Log_File: mysqlbin.000002
             Slave_IO_Running: Yes
            Slave_SQL_Running: No

可以看到,这样是不可取的,并没有解决问题。

5、查看从库上的表mysql.gtid_executed,可以看到如下的结果:

mysql--dba_admin@127.0.0.1 >>select *from mysql.gtid_executed;
+--------------------------------------+----------------+--------------+
| source_uuid                          | interval_start | interval_end |
+--------------------------------------+----------------+--------------+
| d9f94d88-463a-11e9-b424-005056b72c2a |         143504 |       360195 |
+--------------------------------------+----------------+--------------+
1 row in set (0.00 sec)

从这里可以看出,我们只是告诉了从库,143504~360195之间的事务从库已经处理过了,从库并不知道143504之前的事务是否已经执行过,所以将之前的事务也给同步过来了,如果我们将gtid_purged的值改为1-360195,告诉从库1~360195的事务都已经执行完了,这个时候我们看看会有什么效果。

mysql--dba_admin@127.0.0.1 >>set global gtid_purged='d9f94d88-463a-11e9-b424-005056b72c2a:1-360195';
Query OK, 0 rows affected (0.00 sec)

mysql--dba_admin@127.0.0.1 >>change master to master_host='XX.XXX.XXX.161',
    -> master_user='dba_repl',
    -> master_password='XXXXXXX',
    -> master_port=4308,
    -> master_auto_position=1;
Query OK, 0 rows affected, 1 warning (0.02 sec)

mysql--dba_admin@127.0.0.1 >>start slave;show slave status\G
Query OK, 0 rows affected (0.01 sec)

*************************** 1. row ***************************
               Slave_IO_State: Checking master version
                  Master_Host: XX.XX.XXX.161
                  Master_User: dba_repl
                  Master_Port: 4308
                Connect_Retry: 60
              Master_Log_File: 
          Read_Master_Log_Pos: 4
               Relay_Log_File: slave-relay-bin.000001
                Relay_Log_Pos: 4
        Relay_Master_Log_File: 
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

可以看到,主从复制关系已经搭建好了,也就是说,从库需要知道当前已经执行过那些gtid的值,然后将1开始,到当前编号的值都设置为gtid_purged,然后再去搭建主从复制关系,这样的话,从库才可以从正确的gtid开始,去重新复制主库上的操作。

总结一下:

在使用GTID搭建主从复制的时候,需要给从库设置正确的gtid_purged的值,然后使用auto_position=1的方法去搭建主从复制。

如果你是使用备份的方法搭建,需要在备份文件中找到备份的那个时间点的gtid_purged值。

如果你是将已有的复制关系更改为gtid的方式,则你需要stop slave之后,抓到当前已经执行完成的gtid的值,作为从库的gtid_purged值,然后再开启复制关系。

还有一种情况,如果你使用gtid无法第一时间搭建成功主从复制,也就是没有出现双yes的情况,而这个时候从库已经落后主库很多了,那么可以考虑先用偏移量的方式先保证从库追上主库,然后再切换到gtid。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-08-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DBA随笔 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 MySQL
腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档