• MySQL案例-GTID同步失败:master has purged binary logs


    GTID工具联动:http://blog.itpub.net/29510932/viewspace-1736132/
    -------------------------------------------------------------------------------------------------正文---------------------------------------------------------------------------------------------------------------

    场景:
    MySQL-5.7.12, 开启GTID, M1和M2双主同步, S1从库, RC隔离级别
    背景:
    因为网络波动导致S1的Master从M1切换到了M2, 切换过去以后同步失败, 报错信息如下:
    Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has purged binary logs containing GTIDs that the slave requires.'

    分析:
    从报错信息上很明显能看出是M2主库purge掉了S1从库还没有receive的事务, 所以报错了;

    着手处理:
    不过印象中这个业务库本身应该是没什么业务流量的, 不至于需要purge掉binlog;
    遂登录主库M2看一下:
    binlog日志都在.......


    那么就很奇怪了....M2的binlog没有purge过, 为什么会报这个ER_MASTER_HAS_PURGED_REQUIRED_GTIDS的错误呢?
    考虑到时间紧迫, 临时用log_file和position的方式恢复了M2与S1的同步;

    确认没有再出现问题以后, google+翻了一下源代码;

    根据关键字ER_MASTER_HAS_PURGED_REQUIRED_GTIDS找到~/mysql/sql/rpl_binlog_sender.cc的第744行,

    点击(此处)折叠或打开

    1. if (!gtid_state->get_lost_gtids()->is_subset(m_exclude_gtid))
    2.     {
    3.       errmsg= ER(ER_MASTER_HAS_PURGED_REQUIRED_GTIDS);
    4.       global_sid_lock->unlock();
    5.       set_fatal_error(errmsg);
    6.       return 1;
    7.     }


    结合一部分注释, 以及代码上下文的内容, 可以知道M2在初始化dump线程的时候, 会检查S1的一些GTID相关的状态,
    这段代码会检查从库是否能"继续"从主库同步事务;
    判断的条件可以简单描述为:主库不能purge掉从库还没有execute的事务(或者是主库压根就没有那一部分日志);

    一直到这里, 都证明了最初的判断是没问题的, 那为什么M2的binlog全部都在, 但是S1又报这个错误了?
    登录M2, 看一下GTID_Purged的信息,


    居然还真的有purged的信息, 不过这个UUID并不是M2的, 而是M1的;
    在replication中, 会有这么一种现象:通过replication获得的事务,在SQL thread复现完以后, 会自动purge掉;
    所以在M2上面, 就出现了M1的GTID被purge的信息;
    由于M1和M2并没有开启slave-log-update, 所以S1在以M2为主库的时候,无法获取到M1的事务,
    而切换的过程中, S1断开了与M1的连接, 在建立起与M2的连接前, M2复现了一些M1的事务, 并Purge掉了;
    当S1的master切换到M2以后, 在dump前, 会检查到M2上9cfe6b63-3e90-11e6-a1db-525400e9a4af:1-66177的事务都全部purge掉了,

    所以S1连接到M2之后,发现S1的executed_gtid中, 9cfe6b63-3e90-11e6-a1db-525400e9a4af的事务低于66177(凭记忆, 报错的时候是33000多,估计是因为网络的波动的原因, 同步中断了有一阵子了), 所以报出了之前的错误:master has purged binary logs;

    之后在测试环境搭建了一套测试环境, 在Master的GTID_Purged超过Slave的Executd_GTID时, 必定会报出这个错误, 不论这个GTID的UUID是不是Master自己的;

    总结:
    所以在这个案例中,最合适的做法是在S1上面Purge掉主库已经Purged的事务, 然后再使用auto_position=1的方式进行同步;
    以后再遇到类似的问题, 也可以遵循一个基本的原则来判断是需要purge, 还是跳过:
    从库在开始同步前,主库会依靠GTID来确认从库在开始同步以后, 能够把每一个主库上执行过的事务(包括slave的SQL Thread)都复现一次,最终保持和主库完全一致;
    判断方法也很简单,基本基于两个条件:
    1.主库不能purge从库还没有execute的事务(即从库的executed_GTID要大于主库的GTID_Purged);
    2.主库上的事务号不能低于从库(即从库的executed_GTID的最后一个事务要在主库的executed_GTID的范围之内);
    PS: 在这个案例中, 由于从库已经获取不到从33000多到66177的事务了(主库GTID_Purged中的记录), 所以不符合条件1终止同步过程, 并报错;

  • 相关阅读:
    C++ 纸牌 今日头条面试题
    c++ 病句 今日头条面试题
    C++ 球迷 今日头条面试题
    C++ 活动安排
    C++ 弗洛伊德算法
    填坑 bzoj3337
    bzoj3884 上帝与集合的正确用法
    人参中第一次膜你退货
    洛谷P2216 [HAOI2007]理想的正方形
    洛谷 P1099 树网的核+P2491 [SDOI2011]消防
  • 原文地址:https://www.cnblogs.com/xzlive/p/14003667.html
Copyright © 2020-2023  润新知