内容简介:深坑!!!请注意!在Mysql group replication发现的”丢失数据”的场景
之所以想使用基于paxos协议的group replication,目的是为了更好的保障数据库的数据安全,包括数据一致性以及数据零丢失。目前虽然采用半同步,可以保障数据的安全,但在极端情况下,出现数据库主从误切的时候,出现老主库跟新主库同时都有写入的场景时,就破坏了数据一致性。为了避免这个状况,基于paxos协议支持多节点写入的技术开始在 mysql 各种版本上使用。 mysql官方也采用的group replicaiton 插件来实现这个功能。
在进行group replication的测试过程中,惊奇地发现以下现象:
特别说明一下,group replication的模式为single primary。 因为一些原因,导致原来primary节点被驱逐,集群内部重新选举了新的primary 节点, 切换之后不再有 sql 操作。
新primary节点的gtid 如下:
gtid_executed | aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1-9578875, d5e35917-4cde-11e7-9791-1c98ec1cbc64:1-6
原来的primary节点重起之后,查看一下其gtid的信息。
gtid_executed | aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1-9578876, d5e35917-4cde-11e7-9791-1c98ec1cbc64:1-6
aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1-9578876 比
aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1-9578875 多一个事务。 也就是老的primary节点比新的primary节点多了一个事务? 为什么有最后1个事务没有传送到新的主库? 原因作者目前也不知道。 我们来看一下最后一个事务是什么事务:
# at 626 #170612 11:03:20 server id 128283359 end_log_pos 687 GTID last_committed=1 sequence_number=2 SET @@SESSION.GTID_NEXT= 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:9578876'/*!*/; # at 687 #170612 11:03:20 server id 128283359 end_log_pos 746 Query thread_id=6 exec_time=499 error_code=0 SET TIMESTAMP=1497236600/*!*/; BEGIN /*!*/; # at 746 #170612 11:03:20 server id 128283359 end_log_pos 925 View_change_log_event: view_id=14972366013867880:2 # at 925 #170612 11:03:20 server id 128283359 end_log_pos 990 Query thread_id=6 exec_time=499 error_code=0 SET TIMESTAMP=1497236600/*!*/; COMMIT /*!*/;
我们看到,是一个view change 事件产生的gtid, view change发生在group replication组内节点的加入或者离去的过程中。因此,这个丢失的事务,不是一个业务sql产生的事务。 因此,新主库没有丢失数据。 但是,这是否就没有问题了?继续看后面的内容。
现在我们试图把原来的primary节点加入到group replication复制组中去, 执行start group_replication命令,但该命令会提示错误。查看错误日志文件,得到的信息如下:
2017-06-12T11:09:54.263840+08:00 0 [Note] Plugin group_replication reported: 'A new primary was elected, enabled conflict detection until the new primary applies all relay logs' 2017-06-12T11:09:54.263936+08:00 0 [ERROR] Plugin group_replication reported: 'This member has more executed transactions than those present in the group. Local transactions: aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1-9578876, d5e35917-4cde-11e7-9791-1c98ec1cbc64:1-6 > Group transactions: aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1-9578875, d5e35917-4cde-11e7-9791-1c98ec1cbc64:1-6'2017-06-12T11:09:54.263980+08:00 0 [ERROR] Plugin group_replication reported: 'The member contains transactions not present in the group. The member will now exit the group.'
错误日志 中输出的信息表达得很清楚,就是准备加进来的节点执行的事务比组内的事务还多, 拒绝加入 。
但dba很多时候,“往往不信邪”,第一次执行失败之后,会尝试第二次(作者当时也是如此)。 但是,执行第二次的,却 “妥妥滴”成功了 。 真的是妥妥的吗? 为什么第二次却可以是成功的呢?原因是因为: 执行第一次start group_replication的时候, 因为有view change 事务产生,primary节点的
gtid_executed将增加1个事物,所以新旧primary节点的gtid_executed就完全相等了 ,所以第二次启动的时候不再抱错。 但问题就解决了吗?
假如在新的primary上执行一个业务的sql,使其gtid_excuted增加1, 然后再将老的primary节点加入组复制,结果会是怎么?
我们继续进行试验,实验场景一样,老primary节点的gtid_executed比新的primary 节点gtid_executed多一个事务,但这次我们是先在新的primary节点上执行一个sql,然后再将老的primary节点加入group replication组复制。
此时,我们在新的主库执行一个事务: mysql> select * from xcy_test; +---+------+ | a | b | +---+------+ | 1 | 1 | | 2 | 1 | | 3 | 1 | +---+------+ 3 rows in set (0.00 sec) mysql> insert into xcy_test values(4,5); Query OK, 1 row affected (0.01 sec) mysql> select * from xcy_test; +---+------+ | a | b | +---+------+ | 1 | 1 | | 2 | 1 | | 3 | 1 | | 4 | 5 | +---+------+ 4 rows in set (0.00 sec)
然后在老的primary节点上执行start group_replication 加入复制组,命令没有报错。然后在该节点上查询刚刚插入的记录。 刚刚被插入的数据被没有复制到该节点,数据丢失。好恐怖。。。。
mysql> start group_replication; Query OK, 0 rows affected (2.16 sec) mysql> select * from xcy_test; +---+------+ | a | b | +---+------+ | 1 | 1 | | 2 | 1 | | 3 | 1 | +---+------+ 3 rows in set (0.00 sec)
在作者的暴力测试中,居然发现新的primary节点的执行的事务数比老的primary节点的事务数少,而少的这个事务目前发现是发生选举新主库时产生的view change 事务,虽然不造成新primary丢失业务数据, 但是当老primary再次加入组复制时,该节点将可能丢失数据,不再是一个完整的复制副本 。
组复制的逻辑还是比较复杂,细节也非常多,目前尚未弄清出现这种状况的原因,后续期待大牛跟官方能够提供支持,确认是否是bug?
但测试过程中出现现象也同样值得我们敬畏 。 首先抛开该问题是否是bug,是否可以采用合理的操作步骤来避免这些观念, 仅仅从测试过程出现的现象本身来看,至少可以确认的一点是: “group replication虽然是为了解决主从数据一致性而生,但是,并不代表它完全不会带来破坏数据一致性的缺陷,在这个方面依然需要关注,谨慎甚至敬畏“ 。 从作者的测试过程中发现,排除数据库可能存在的bug, 在隐含的不正确的场景下,进行了看似合理的操作,也将可能引发产生主从数据不一致的现象。 正是因为这些现象, 刷新了作者之前的关注点 ——因为group replication目的就是为了解决数据一致性而引进的,之前的关注点都在它因为有新功能而引进了哪些其他方面的限制。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 高并发场景下,如何保证生产者投递到消息中间件的消息不丢失?【石杉的架构笔记】
- MySQL root 密码丢失重置
- kafka consumer防止数据丢失
- MongoDB 副本集丢失数据的测试
- 苹果CloudKit出现问题:部分应用数据丢失
- React中this丢失的解决方法
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
一个APP的诞生
Carol 炒炒、刘焯琛 / 电子工业出版社 / 2016-7-1 / 79
在移动互联网高度发达的今天,一个个APP,成为我们通向网络世界的窗口。它的诞生流程,令不少对互联网世界产生幻想甚至试图投身其中的年轻人充满了好奇。 《一个APP 的诞生》就是这样一步一步拆分一个APP 的诞生过程。从前期市场调研,竞品分析开始,一直到设计规范,界面图标,设计基础,流程管理,开发实现,市场推广,服务设计,甚至跨界融合,都有陈述。 《一个APP 的诞生》被定义是一本教科书,......一起来看看 《一个APP的诞生》 这本书的介绍吧!