复制4 - GTID

一. GTID的介绍

  1. Global Transaction Identifier – 全局事物ID
  2. GTID = Server_UUID + Transaction_ID
    1. Server_UUID 是全局唯一的
    2. Transaction_ID 是自增的
  3. GTID 的作用是替代 Filename + Position
root@mysqldb 22:28:  [(none)]> show variables like '%server_uuid%';
+---------------+--------------------------------------+
| Variable_name | Value                                |
+---------------+--------------------------------------+
| server_uuid   | 3c993697-f4b8-11ed-a315-000c2953dece |
+---------------+--------------------------------------+
1 row in set (0.01 sec)

在MySQL中看到的 UUID ,实际是保存在 $DATADIR/auto.cnf 中的,且该文件是MySQL服务器初始化的时候自动生成的。

[root@MySQL-Master ~]# cat /data/mysql/auto.cnf
[auto]
server-uuid=3c993697-f4b8-11ed-a315-000c2953dece

通过冷备做备份,拷贝$DATADIR时,记得要把备份中的auto.cnf给删除

 

二. GTID的意义

  • 假设现在没有GTID
    • 当Master宕机后,一个Slave被提升为New Master,如果需要继续维持复制关系,就需要把另外两个Slave的CHANGE MASTER指向New Master;
    • 那问题来了,原来Slave是指向Master的Filename_M + Position_M的位置,现在要指向New Master上新的Filename_N +  Position_N的位置,这两个位置是比较难对应起来的;
    • 此时两个Slave要继续复制(CHANGE MASTER)会比较麻烦。
  • 使用GTID
    • 和上面一样的场景,两个Slave需要重新指向New Master,由于使用了GTID,目前Slave-A获取到的日志对应的GTID=G_A,Slave-B 获取到的日志对应的GTID=G_B;
    • 此时New Master上是存在G_A和G_B(通过选举出来的,获取的日志应该是最多的),那两个Slave就可以直接使用G_A和G_B这两个GTID,通过指向New Master接着继续复制;

 

三. GTID的配置

[mysqld]
log_bin = bin.log
gtid_mode = ON
log_slave_updates = 1  # MySQL 5.6 必须开启参数 log_slave_updates (5.6版本的限制),该参数用于在slave上生成binlog
enforce_gtid_consistency = 1
  1. MySQL 5.6 升级到gtid模式需要停机重启
  2. MySQL 5.7 版本开始可以不开启 log_slave_updates
  3. MySQL 5.7.6 版本开始可以在线升级成gtid模式

 

四. 基于GTID的复制

  1. 在开启GTID后,使用 mysqldump 备份单个数据库时,会有 Warning ,大致意思为你只备份了部分数据库,但是启用GTID后包含了所有的事物。可以忽略该警告。
  2. mysqldump文件中有sql语句: SET @@GLOBAL.GTID_PURGED='3c993697-f4b8-11ed-a315-000c2953dece:1-16';,表示为:这部分的GTIDs对应的事物已经purged,Slave在还原备份后,进行复制时,要跳过这些GTIDs(对应的事物),发生主从复制异常时,也可以临时用这个方式来解决。

 

五. 基于GTID搭建主从复制

用master_auto_position代替binlog具体信息,其他不变

  1. mysqldump出要复制的数据库
  2. 从库导入数据
  3. change master to MASTER_HOST='192.168.220.10', MASTER_USER='repl', MASTER_PASSWORD='123456',master_auto_position=1;
  4. start slave
root@mysqldb 09:52:  [(none)]> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.220.10
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: binlog.000010
          Read_Master_Log_Pos: 670
               Relay_Log_File: relay.000002
                Relay_Log_Pos: 405
        Relay_Master_Log_File: binlog.000010
             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: 670
              Relay_Log_Space: 642
              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: 11
                  Master_UUID: 3c993697-f4b8-11ed-a315-000c2953dece
             Master_Info_File: mysql.slave_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:
            Executed_Gtid_Set: 3c993697-f4b8-11ed-a315-000c2953dece:1-18
                Auto_Position: 1  -- 表示使用GTID复制
         Replicate_Rewrite_DB:
                 Channel_Name:
1 row in set (0.00 sec)

 

六. GTID与Filename-Pos的对应

在binlog中,多了一个GTID的event,如下所示

root@mysqldb 10:03:  [test_1]> show binlog events in 'binlog.000010';
+---------------+------+----------------+-----------+-------------+--------------------------------------------------------------------+
| Log_name      | Pos  | Event_type     | Server_id | End_log_pos | Info                                                               |
+---------------+------+----------------+-----------+-------------+--------------------------------------------------------------------+
| binlog.000010 |    4 | Format_desc    |        11 |         123 | Server ver: 5.7.9-log, Binlog ver: 4                               |
| binlog.000010 |  123 | Previous_gtids |        11 |         194 | 3c993697-f4b8-11ed-a315-000c2953dece:1-16                          |
| binlog.000010 |  194 | Gtid           |        11 |         259 | SET @@SESSION.GTID_NEXT= '3c993697-f4b8-11ed-a315-000c2953dece:17' |  -- 一个GTID的event
| binlog.000010 |  259 | Query          |        11 |         331 | BEGIN                                                              |
| binlog.000010 |  331 | Rows_query     |        11 |         389 | # insert into test_1 values(NULL,10)                               |
| binlog.000010 |  389 | Table_map      |        11 |         439 | table_id: 108 (test.test_1)                                        |
| binlog.000010 |  439 | Write_rows     |        11 |         483 | table_id: 108 flags: STMT_END_F                                    |
| binlog.000010 |  483 | Xid            |        11 |         514 | COMMIT /* xid=26 */                                                |
| binlog.000010 |  514 | Gtid           |        11 |         579 | SET @@SESSION.GTID_NEXT= '3c993697-f4b8-11ed-a315-000c2953dece:18' |
| binlog.000010 |  579 | Query          |        11 |         670 | use `test`; flush privileges                                       |
| binlog.000010 |  670 | Gtid           |        11 |         735 | SET @@SESSION.GTID_NEXT= '3c993697-f4b8-11ed-a315-000c2953dece:19' |
| binlog.000010 |  735 | Query          |        11 |         809 | BEGIN                                                              |
| binlog.000010 |  809 | Rows_query     |        11 |         857 | # insert into t1 values(2)                                         |
| binlog.000010 |  857 | Table_map      |        11 |         904 | table_id: 109 (test_1.t1)                                          |
| binlog.000010 |  904 | Write_rows     |        11 |         944 | table_id: 109 flags: STMT_END_F                                    |
| binlog.000010 |  944 | Xid            |        11 |         975 | COMMIT /* xid=94 */                                                |
| binlog.000010 |  975 | Gtid           |        11 |        1040 | SET @@SESSION.GTID_NEXT= '3c993697-f4b8-11ed-a315-000c2953dece:20' |
| binlog.000010 | 1040 | Query          |        11 |        1114 | BEGIN                                                              |
| binlog.000010 | 1114 | Rows_query     |        11 |        1162 | # insert into t1 values(3)                                         |
| binlog.000010 | 1162 | Table_map      |        11 |        1209 | table_id: 109 (test_1.t1)                                          |
| binlog.000010 | 1209 | Write_rows     |        11 |        1249 | table_id: 109 flags: STMT_END_F                                    |
| binlog.000010 | 1249 | Xid            |        11 |        1280 | COMMIT /* xid=95 */                                                |
+---------------+------+----------------+-----------+-------------+--------------------------------------------------------------------+
22 rows in set (0.00 sec)

通过扫描binlog中的GTID值,就可以知道GTID与Filename-Pos对应的关系,但是如果binlog非常大,扫描的量也是会很大的,所以在binlog开头部分有一个Previous_gtids的event,如下所示:

root@mysqldb 10:06:  [test_1]> show binlog events in 'binlog.000011'\G
*************************** 1. row ***************************
   Log_name: binlog.000011
        Pos: 4
 Event_type: Format_desc
  Server_id: 11
End_log_pos: 123
       Info: Server ver: 5.7.9-log, Binlog ver: 4
*************************** 2. row ***************************
   Log_name: binlog.000011
        Pos: 123
 Event_type: Previous_gtids  -- 表示在此之前,GTID运行到的范围是哪里
  Server_id: 11
End_log_pos: 194
       Info: 3c993697-f4b8-11ed-a315-000c2953dece:1-20
*************************** 3. row ***************************
   Log_name: binlog.000011
        Pos: 194
 Event_type: Gtid
  Server_id: 11
End_log_pos: 259
       Info: SET @@SESSION.GTID_NEXT= '3c993697-f4b8-11ed-a315-000c2953dece:21'

如果我要的GTID比Previous_gtids的大,就扫描当前文件,反之则扫描之前的文件,依次类推。
因为binlog在rotate(rotate events)的时候,是知道当前最大的GTID的,可以将该值写入到下一个新的binlog的开头,即Previous_gtids

posted @   BinBin-HF  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示