sql_log_bin在GTID复制下的一个现象

背景

现网环境是M-M GTID+haproxy+组成的高可用需要做一个基于时间点的回档

之前的方法:

1 新建出另外一组M-M GTID高可用集群。我们将新的集群成为B,旧的集群称为A

2  分别导入A的历史备份到B集群的两个实例上,分开导入,导入期间双主同步不关,但会关闭sql_log_bin

3 分别导入A的增量binlog到B集群的两个实例上,分开导入,导入期间双主同步不关,但会关闭sql_log_bin


结果发现集群B并没有回档到预期的效果,有时B上的主节点丢失增量数据,有时B上的备用节点丢失增量数据


原因分析

通过分析,发现是gtid复制引起的原因,即在B集群的主节点上执行A的增量binlog时,即使这时我们将sql_log_bin关闭了,但是依旧会产生一些binlog,发现这些binlog都是一些带A集群节点uuid的空事务,而这些空事务也会产生一个个的gtid传到B集群的备用节点;当B集群的备用节点执行增量binlog时,发现之前自己"似乎已经"执行过了,于是就跳过了这些增量操作,导致B几群的备用节点丢失这些增量数据

场景模拟

mysql> reset master;
Query OK, 0 rows affected (0.00 sec)


mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      151 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)


mysql> select * from xx;
Empty set (0.00 sec)


mysql> set sql_log_bin=0;
Query OK, 0 rows affected (0.00 sec)


mysql> insert into xx values(123);
Query OK, 1 row affected (0.00 sec)


mysql> select * from xx;
+------+
| id   |
+------+
|  123 |
+------+
1 row in set (0.00 sec)


mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 |      151 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

//可以发现当sql_log_bin关闭后,再执行简单的insert是不会产生binlog的


mysql> SET @@SESSION.GTID_NEXT='8356b68c-5cfb-11e7-b683-6c92bf2352b8:1';
Query OK, 0 rows affected (0.00 sec)


mysql> begin;
Query OK, 0 rows affected (0.00 sec)


mysql> insert into xx values(234);
Query OK, 1 row affected (0.00 sec)


mysql> commit;
Query OK, 0 rows affected (10.00 sec)


mysql> SET @@SESSION.GTID_NEXT='AUTOMATIC';
Query OK, 0 rows affected (0.00 sec)


mysql> show master status;
+------------------+----------+--------------+------------------+----------------------------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                      |
+------------------+----------+--------------+------------------+----------------------------------------+
| mysql-bin.000001 |      346 |              |                  | 8356b68c-5cfb-11e7-b683-6c92bf2352b8:1 |
+------------------+----------+--------------+------------------+----------------------------------------+
1 row in set (0.00 sec)

//可以发现当指定了另外一个uuid的gtid事务后,再insert记录时,产生了binlog

SET @@SESSION.GTID_NEXT= '8356b68c-5cfb-11e7-b683-6c92bf2352b8:1'/*!*/;
# at 199
#170704 17:22:29 server id 168410320  end_log_pos 272 CRC32 0x232648e0 Query thread_id=1524016 exec_time=0 error_code=0
SET TIMESTAMP=1499160149/*!*/;
SET @@session.pseudo_thread_id=1524016/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1073741824/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=33/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
BEGIN
/*!*/;
# at 272
#170704 17:22:29 server id 168410320  end_log_pos 346 CRC32 0x5661cdc7 Query thread_id=1524016 exec_time=0 error_code=0
SET TIMESTAMP=1499160149/*!*/;
COMMIT
/*!*/;
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;

//解析了产生的binlog后发现,这些binlog实际都是空事务,也就是说把insert into xx values(234);这条sql过滤了,但是gtid信息却是不会过滤,记录了下来,而这些信息传到备库,肯定会影响上述恢复的逻辑,备库误以为这些gtid已经执行过了,遂不会再执行备库的增量binlog


参数理解

sql_log_bin只是让SQL内容不在binlog里显示,但是gtid的信息并无法屏蔽,查看官网对该参数解释有点含糊不清

Setting this variable to 0 prevents GTIDs from being assigned to transactions in the binary log. If you
are using GTIDs for replication, this means that, even when binary logging is later enabled once again,
the GTIDs written into the log from this point do not account for any transactions that occurred in the
meantime—in effect, those transactions are lost.


解决方法

知道了原因,解决方法就非常多样了,最简单的方法,也就是上述代码量更改最小的,就是mysqlbinlog在解析增量部分的binlog时,加上

 --skip-gtids=true,这样解析出来的binlog就不会存在gtid信息,自然就不会有上述现象了




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值