• 欢迎访问DBA的辛酸事儿,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站
  • 欢迎大家关注博主公众号:DBA的辛酸事儿
  • 博文中若有错误的地方,请大家指正,大家的指正是我前进的动力

基于GTID方式搭建MySQL 5.7 主从复制环境

MySQL SEian.G 6年前 (2019-02-28) 1863次浏览 已收录 0个评论
文章目录[隐藏]

前面的一篇文章中介绍了基于传统的方式搭建主从复制环境:使用传统的方式打建MYSQL 5.7异步复制环境

一、什么是GTID

GTID是MySQL 5.6的新特性之一,加入了全局事务ID (Global Transaction ID,简称GTID) 来强化数据库的主备一致性,故障恢复,以及容错能力。用于取代传统方式通过binlog以及postion号来定位复制位置的传统方式。借助GTID,在发生主备切换的情况下,MySQL的其它Slave可以自动在新主上找到正确的复制位置,这大大简化了复杂复制拓扑下集群的维护,也减少了人为设置复制位置发生误操作的风险。另外,基于GTID的复制可以忽略已经执行过的事务,减少了数据发生不一致的风险。

那么,GTID长什么样?

根据官方文档定义,GTID由source_id+transaction_id构成。

GTID = source_id:transaction_id

上面的source_id指示发起事务的MySQL实例,值为该实例的server_uuid。server_uuid由MySQL在第一次启动时自动生成并被持久化到auto.cnf文件里,transaction_id是一个从1开始的自增计数,表示在这个主库上执行的第n个事务。MySQL会保证事务与GTID之间的1 : 1映射。例如:

c9eeb85d-de5b-11e8-80d4-525400cf9369:1

表示在以 “c9eeb85d-de5b-11e8-80d4-525400cf9369″为唯一标识的MySQL实例上执行的第1个数据库事务。

很容易理解,MySQL只要保证每台数据库的server_uuid全局唯一,以及每台数据库生成的transaction_id自身唯一,就能保证GTID的全局唯一性。

一组连续的事务可以用’-‘连接的事务序号范围表示。例如:

c9eeb85d-de5b-11e8-80d4-525400cf9369:1-5

更一般的情况是GTID的集合。GTID集合可以包含来自多个source_id的事务,它们之间用逗号分隔;如果来自同一source_id的事务序号有多个范围区间,各组范围之间用冒号分隔,例如:

c9eeb85d-de5b-11e8-80d4-525400cf9369:1-5:11-18,

e6954592-8dba-11e6-af0e-fa163e1cf3f2:1-27

可以使用show master status实时看当前的事务执行数。

那什么是server_uuid?

MySQL 5.6用128位的server_uuid代替了原本的32位server-id的大部分功能。原因很简单,server-id依赖于my.cnf 的手工配置,有可能产生冲突 —— 而自动产生128位uuid的算法可以保证所有的MySQL uuid都不会冲突。
MySQL5.6在数据目录下有一个auto.cnf文件就是用来保存server_uuid的,如下:

[root@VM_54_118_centos ~]# cat /data/mysql/mysql_3306/data/auto.cnf 
[auto]
server-uuid=c9eeb85d-de5b-11e8-80d4-525400cf9369

在 MySQL 再次启动时会读取auto.cnf文件,继续使用上次生成的 server_uuid。使用SHOW命令可以查看MySQL实例当前使用的server_uuid;

root@localhost [(none)]>SHOW GLOBAL VARIABLES LIKE 'server_uuid';
+---------------+--------------------------------------+
| Variable_name | Value                                |
+---------------+--------------------------------------+
| server_uuid   | c9eeb85d-de5b-11e8-80d4-525400cf9369 |
+---------------+--------------------------------------+
1 row in set (0.00 sec)

你可以使用基于语句的或基于行的复制与GTID,但是,为了获得最佳效果,生产环境中,建议你使用基于行ROW的格式。

另外支持启用GTID,对运维人员来说应该是一件令人高兴的事情,在配置主从复制,传统的方式里,你需要找到binlog和pos点,然后change master to指向,而不是很有经验的运维,往往会将其找错,造成主从同步复制报错,在MySQL 5.6里,如果使用了GTID,启动一个新的复制从库或切换到一个新的主库,就不必依赖log文件或者pos位。只需要知道master的IP、端口,账号密码即可,因为同步复制是自动的,mysql通过内部机制GTID自动找点同步。

那和传统方式相比,基于GTID的复制有什么优点?

  • 在传统的复制里面,当发生故障,需要进行主从切换时,需要找到binlog和pos点,然后change master to指向新的master,相对来说比较麻烦,也容易出错。在MySQL 5.6里面,不用再找binlog和pos点,我们只需要知道master的ip,端口,以及账号密码就行,因为复制是自动的,MySQL会通过内部机制GTID自动找点同步。
  • 多线程复制(基于库),在MySQL 5.6以前的版本,slave的复制是单线程的。一个事件一个事件的读取应用。而master是并发写入的,所以延时是避免不了的。唯一有效的方法是把多个库放在多台slave,这样又有点浪费服务器。在MySQL 5.6里面,我们可以把多个表放在多个库,这样就可以使用多线程复制,当只有1个库,多线程复制是没有用的。

那么基于GTID复制实现的工作原理是什么呢?

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

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

3)sql线程从relay log中获取GTID,然后对比slave端的binlog是否有记录(所以MySQL5.6 SLAVE必须要开启二进制日志记录)。

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

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

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

注意:所以建议每一张表都要创建一个主键,尽量的避免主从延迟的产生;

小结

1)使用master_auto_position=1代替基于binlog和position号的主从复制方式,更便于主从复制的搭建

2)gtid可以知道事务在最开始是在哪个实例上提交的

3)gtid方便实现主从间failover,再也不用不断地找position和binlog了

关于更多基于GTID的详细内容可参考:

https://dev.mysql.com/doc/refman/5.7/en/replication-options-gtids.html

 

好了,上面介绍了这么多的GTID相关的理论知识,看的都有点累了,下面我们就搭建一个基于GTID方式的主从复制环境;

二、GTID方式搭建主从复制环境

在前面的一篇文章中使用传统方式大家MYSQL 5.7异步复制环境;搭建了基于传统方式的主从环境,下面我们再次基础上,搭建基于GTID方式的主从复制环境

主库:

gtid-mode = ON
enforce-gtid-consistency = ON

从库:

gtid-mode = ON
enforce-gtid-consistency = ON
log-slave-updates = ON

在从库清除原有的主从复制关系

root@localhost [(none)]>stop slave;
Query OK, 0 rows affected (0.05 sec)

root@localhost [(none)]>reset slave all;
Query OK, 0 rows affected (0.28 sec)

root@localhost [(none)]>show slave status\G;
Empty set (0.01 sec)

关闭主库和备库

[root@wjq1 data]# mysqladmin -u root -pqcloud@2018 shutdown
[root@wjq2 data]# mysqladmin -u root -pqcloud@2018 shutdown

重新启动主从

[root@wjq1 data]# mysqld_safe --defaults-file=/etc/my.cnf &
[root@wjq2 data]# mysqld_safe --defaults-file=/etc/my.cnf &

root@localhost [(none)]>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       |
+----------------------------------+-----------+
8 rows in set (0.16 sec)

建立主从同步关系

root@localhost [(none)]>change master to 
    -> master_host='10.10.1.10',
    -> master_user='wjqrepl',
    -> master_password='qcloud@2018',
    -> master_port=3306,
    -> master_auto_position=1;
Query OK, 0 rows affected, 2 warnings (0.05 sec)

root@localhost [(none)]>start slave;
Query OK, 0 rows affected (0.02 sec)

root@localhost [(none)]>show slave status\G; 
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.10.1.10
                  Master_User: wjqrepl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql3306.000009
          Read_Master_Log_Pos: 436
               Relay_Log_File: wjq2-relay-bin.000002
                Relay_Log_Pos: 649
        Relay_Master_Log_File: mysql3306.000009
             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: 436
              Relay_Log_Space: 855
              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: 330610
                  Master_UUID: dadc5a32-e0c9-11e8-9dd3-000c29c743b3
             Master_Info_File: /data/mysql/3306/data/master.info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           Master_Retry_Count: 86400
                  Master_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: dadc5a32-e0c9-11e8-9dd3-000c29c743b3:1
            Executed_Gtid_Set: dadc5a32-e0c9-11e8-9dd3-000c29c743b3:1
                Auto_Position: 1
         Replicate_Rewrite_DB: 
                 Channel_Name: 
           Master_TLS_Version: 
1 row in set (0.00 sec)

如上所述,基于GTID方式的主从复制环境搭建完成;


  • 5.7之后,gtid_executed这个值持久化了,在mysql库下新增了一张表:gtid_executed
    该表会记录已经执行的gtid集合的信息,有了这张表,就不用再像5.6版本时,必须开启log_slave_updates参数,从库才可以进行复制。gtid信息会保存在gtid_executed表中,可以关闭从库binlog,节约binlog记录开销。执行reset master时,会清空表内所有数据
  • 5.7还有gtid_executed_compression_period参数,控制gtid_executed表压缩,默认值为1000,表示执行完1000个事务后开始压缩
  • 5.7.6开始,gtid_mode支持动态修改,值有:OFF/OFF_PERMISSIVE/ON_PERMISSIVE/ON
    OFF,关闭gtid事务
    OFF_PERMISSIVE,新事务是匿名的,同时允许复制的事务可以是gtid,也可以是匿名的
    ON_PERMISSIVE,新事务使用gtid,同时允许复制的事务可以是gtid,也可以是匿名的
    ON,支持gtid事务
    生产环境中,可能有把传统复制改为gtid复制的需求,gtid_mode不支持跳跃式修改
    从库上可以通过show slave status获取接收的gtid(retrieve_gtid_set)和执行的gtid(execute_gtid_set)

参数说明:

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,否则,下次执行事务时会报错。

基于GTID方式搭建MySQL 5.7 主从复制环境


如果您觉得本站对你有帮助,那么可以收藏和推荐本站,帮助本站更好地发展,在此谢过各位网友的支持。
转载请注明原文链接:基于GTID方式搭建MySQL 5.7 主从复制环境
喜欢 (4)
SEian.G
关于作者:
用心去记录工作,用心去感受生活,用心去学着成长;座右铭:苦练七十二变,笑对八十一难
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址