GTID 模式 - 通过跳过事务解决主从故障

文若11个月前技术文章321

一、前言

很多场景下我们需要跳过一个事务来修复主从关系,例如主从事务不一致,或者对无主键表更新,导致较大延迟,操作过程在此记录。

二、操作流程

1. 获取最后一个 GTID 操作

在 GTID 模式下,如果需要跳过一个事务,就需要先获得从库执行的最后一个 GTID 操作,可以通过下方几种方法获得:

  1. show slave status:

    Executed_Gtid_Set: 2102e47a-a63b-11eb-b2a1-fa85c353c300:1-68835,
    741e7d25-a5a2-11eb-a8d2-facd1b9d5200:1-1691060:1691062-1696109,
    aeccf6dc-c76d-11eb-a563-fab7dbe5cd00:1-38,
    eab37148-e44b-11eb-a993-fa85c353c300:1-2

    这里主要看 Executed_Gtid_Set 变量。

  2. show master status:

    *************************** 1. row ***************************
    File: mysql-bin.000014
    Position: 234
    Binlog_Do_DB:
    Binlog_Ignore_DB:
    Executed_Gtid_Set: 2102e47a-a63b-11eb-b2a1-fa85c353c300:1-68835,
    741e7d25-a5a2-11eb-a8d2-facd1b9d5200:1-1691060:1691062-1696109,
    aeccf6dc-c76d-11eb-a563-fab7dbe5cd00:1-38,
    eab37148-e44b-11eb-a993-fa85c353c300:1-2
    1 row in set (0.01 sec)

    这里主要看 Executed_Gtid_Set 变量。

    如果数据库有多次切换,Executed_Gtid_Set 中的 GTID SET 比较多,我们只看当前主库的 server_uuid 的 GTID SET 即可。 主库的 UUID 可以通过 select @@server_uuid; 查到。

2. 跳过一个事务

stop slave;
set session gtid_next='72170331-ae27-11eb-b3a1-000c29169a83:96174';
begin;commit;
set session gtid_next='AUTOMATIC';
start slave;

在 GTID 模式下,传统复制参数 sql_slave_skip_counter 不能使用。

三、案例

1. 问题描述

CREATE TABLE `order_temp` (
 `order_code` varchar(10) DEFAULT NULL,
 `order_status` varchar(255) DEFAULT NULL,
 `order_time` varchar(255) DEFAULT NULL,
 `account_status` varchar(255) DEFAULT NULL,
 `receivable` decimal(10,2) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

一张无主键表,开发想将 receivable 值全部修改为 3 因为测试环境,直接全表更新,在主库不到一分钟就执行成功了,没想到备库跑了两天都没有结束。

update order_temp set receivable = 3;

2. 原因分析

使用 row 模式复制 binlog 按行存储,回放的时候也是一行一行去改,因为该表没有主键索引,每一次修改都是一次全表扫描,一次全表扫描需要两秒,表中有 4998000 行数据:

4998000 * 2 / 3600 / 24 = 155 天

如果不处理的话,估计得跑上小半年,这个备库也算是废了。

3. 处理过程

  1. 确认主库 uuid 在主库查:

    root@mysql 14:43:  [rep_test]>select @@server_uuid;
    +--------------------------------------+
    | @@server_uuid                        |
    +--------------------------------------+
    | 741e7d25-a5a2-11eb-a8d2-facd1b9d5200 |
    +--------------------------------------+
    1 row in set (0.00 sec)
  2. 确认从库最后一个事务:

    *************************** 1. row ***************************
    File: mysql-bin.000014
    Position: 234
    Binlog_Do_DB:
    Binlog_Ignore_DB:
    Executed_Gtid_Set:
    2102e47a-a63b-11eb-b2a1-fa85c353c300:1-68835,
    741e7d25-a5a2-11eb-a8d2-facd1b9d5200:1-1691060:1691062-1696109,
    aeccf6dc-c76d-11eb-a563-fab7dbe5cd00:1-38,
    eab37148-e44b-11eb-a993-fa85c353c300:1-2
    1 row in set (0.00 sec)

    第二行就是该实例主库的 uuid 最后一个事务是 1696109

  3. 停止复制: 该步骤可能持续时间较长,这个和修改的数据量和延迟的时长有关系,此刻需要回滚已经应用的 event。

    stop slave;
  4. 跳过复制: 刚才最后一个事务是 1696109 正在执行的事务就是 1696109 + 1 = 1696110

    set session gtid_next='741e7d25-a5a2-11eb-a8d2-facd1b9d5200:1696110';
    begin;commit;
    set session gtid_next='AUTOMATIC';
  5. 修复数据 跳过事务,则主库的更新操作没有在从库应用,已经被回滚,此时可以手动在从库跑一下该 SQL。不同的场景有不用的修复方法,此时就跑原 SQL 即可。 修复数据时,要注意如果有级联复制,这种特殊操作前,临时会话级别关闭 binlog

    set session sql_log_bin = 0;
  6. 重新启动复制

    start slave;

    启动后观察主从延迟情况。


相关文章

MySQL运维实战之ProxySQL(9.5)proxysql和MySQL Group Replication配合使用

如果后端MySQL使用了Group Replication,可通过配置mysql_group_replication_hostgroups表来实现高可用mysql_group_replication_...

kubernetes调度策略

1、背景在 Kubernetes 中,调度 (scheduling) 指的是确保 Pod 匹配到合适的节点,以便 kubelet 能够运行它们。调度的工作由调度器和控制器协调完成。调度器通过 Kube...

短信服务开通

短信服务开通

一、添加模版二、添加签名注意开通港澳台签名如果和国内签名冲突,需要修改国内签名 试用场景为通用,三、子账号授权新建RAM用户并创建AK信息提供 签名名称 以及模版CODE即可参考链接: https:/...

hive元数据迁移

hive元数据迁移

一、在新集群中创建hive数据库,作为新集群中的元数据库。注意点:创建hive数据库时注意用户和用户的权限及使用的编码格式一致。查看旧集群中角色权限和编码格式,在新的hive元数据库中设置相同的角色权...

企业级大数据安全架构(二)

企业级大数据安全架构(二)

2安全方案2.1 Knox访问控制Apache Knox是一个通过REST API和UI与Apache Hadoop 部署交互的应用网关。Knox网关为所有与Hadoop集群的REST和HT...

某客户k3s网络故障案例

某客户k3s网络故障案例

1、出现问题     在我们吃饭的过程中,小丫告诉我客户的系统出现问题了,我们赶快吃完饭回去帮忙排查。当我们回去的时候,被告知问题已经被修复了,但是问题根源没有找到。故障原因给出的是:  服务重启后对...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。