背景: 一个公司从初创到公司业务壮大,在数据库的使用都会面临类似的过程。
- 公司起步,会创建一个DB1,陆陆续续将设计的Table都存放在这个库中。
- 公司运行一年,DB里累计了100张Table
- 公司业务模块细分,需要对DB进行拆库,拆分成DB_1,DB_2,DB_3 三个业务数据库。
- 表迁移的需求就发生了
表迁移的主要场景有两种:
- 从DB1中,将部分Table拆分到DB2中,DB2为空库。
- 从DB1中,将部分Table拆分到DB2中,DB2为已经使用的业务数据库。
针对两种方案,有非常多的迁移手段,而迁移之前数据是否持续同步,或者迁移过程dump load等类似方式,会决定了业务的影响时间。
相信大多数情况下,我们都需要业务影响时间尽量短,所以数据库之间的持续同步成为了首选,我们有一种手段:Master-Slave Replication Filter
数据库如果是集群下,数据迁移就演变成了不同集群之间的数据迁移。但MySQL随着5.7的稳定以及8.0的到来,HA主流方案已经不止限于传统的额Master-Slave,PXC和MGR的使用方越来越多。
所以我们今天就主要来聊聊MGR Replication Filter和PXC Replication Filter的数据迁移方案。
--------------------------------华丽的分割线--------------------------
Cluster A 希望从node3节点,将T1表同步Cluster B集群的备节点上.因为考虑B集群有业务使用,因为不希望影响主要的写节点和读节点。并且MGR集群之间的节点是相互同步的,前提是通过修改调整参数group_replication_single_primary_mode=0来实现每个节点都可以提供对外的写能力。
而Replication Filter,需要通过设置Replicate_DB_Table='DB1.T1'来进行过滤。
这样就可以实现t1表从Cluster A到 Cluster B的准实时同步了。
但“坑”就在这里悄然无息的挖出来给你了 - Cluster B如果是MGR或者PXC,那么这个集群的节点之间会出现数据不一致。
一、PXC Replication Filter 的数据不一致
数据库版本:PXC 5.7.25
Replicate_Do_Table: DB1.T1
现象:
- PXC 其中一个节点,充当SLAVE,接收node3节点传输过来的全部binlog,并通过replicationfilter应用DB1.T1表的数据,T1表数据同步到PXC其他节点上是成功的。
- 业务应用,对非salve的PXC节点,进行DML操作(非T1表):同步到其他非slave节点,成功;同步到salve的pxc节点,失败。
- 业务应用,对非salve的PXC节点,进行DDL操作(非T1表):同步到其他非slave节点,成功;同步到salve的pxc节点,成功。
从而发生了节点之间数据不一致的情况,此时,如果业务应用的写入口由于故障或者某种原因,切换到了PXC作为SLAVE的节点上,对不一致的数据进行了操作,从而会导致其余全部非SLAVE的PXC节点,由于数据错误,全部自动关闭数据库实例,进而只剩下一个充当SLAVE的节点,由于多数节点都关闭了,顾集群整体故障。
二、MGR(5.7) Replication Filter 的数据不一致
数据库版本:MySQL 5.7.25
Replicate_Do_Table: DB1.T1
现象:
- MGR 其中一个节点,充当SLAVE,接收node3节点传输过来的全部binlog,并通过replication filter应用DB1.T1表的数据,T1表数据同步到MGR其他节点上是成功的。
- 业务应用,对非salve的MGR节点,进行DML操作(非T1表):同步到其他非slave节点,成功;同步到salve的MGR节点,失败。
- 业务应用,对非salve的MGR节点,进行DDL操作(非T1表):同步到其他非slave节点,成功;同步到salve的MGR节点,失败(注意:此环节与PXC不同,PXC DDL会同步成功)。
从而发生了节点之间数据不一致的情况,此时,如果业务应用的写入口由于故障或者某种原因,切换到了MGR作为SLAVE的节点上,对不一致的数据进行了操作,从而会导致其余全部非SLAVE的MGR节点,由于数据错误,全部自动关闭了集群(并没有关闭实例),进而只剩下一个充当SLAVE的MGR节点,由于多数节点都退出了集群,顾集群整体故障。
如果在group_replication_single_primary_mode=1的情况下,5.7版本MGR的非Primary节点是无法设置Replication Filter的。
但是!!! MySQL 8.0解决了此问题!!!
三、MGR(8.0) Replication Filter 的数据一致了
数据库版本:MySQL 8.0.13
Replicate_Do_Table: DB1.T1
原因:
MySQL 8.0 在以上情况,数据一致了,这是为什么呢?首先我们需要先了解下MGR具备了两个Channel
- group_replication_recovery :该channel主要处理节点加入集群或者启动过程,同步并应用之前积压的binlog event。
- group_replication_applier: 节点在积压历史数据同步结束,集群节点出于可服务的状态,通过该channel来应用集群其他节点的Binlog Event。
既然是channel,那么就和MySQL的多源复制非常像了,而Replication_Filter作为全局的筛选规则,作用在了每个channel中,顾集群节点同步过来的消息,会被本地的group_replication_applier和group_replication_recovery两个channel的replicate_db_table过滤掉了。导致了数据不一致。但这个现象是5.7以及之前的版本。
而MySQL 8.0 提供了Global级别Replication Filter和 Channel级别的Replication Filter:
在8.0下,默认设置Replication Filter会进入Global级别,不影响每个Channel的Replication Filter。特别指定了Channel会进入Channel级别。
MGR的两个Channel无法设置Channel级别的Replication Filter。
所以,既然无法为MGR设置Replication Filter,数据自然在MGR节点之间的流动就正常了。
PXC虽然没有类似的channel,但内部应用binlog event 也基于了sql_thread的机制。
最后两个“但是”!
- 但是1:说了这么多,5.7版本下,如何处理上面数据不一致的问题呢?? 解决办法非常简单:只要将应用程序的写节点,作为Slave节点即可,也就是将全部写入口归类到一个MGR或者PXC节点上。
- 但是2:5.7下,如果业务对MGR和PXC是多节点同时写入的架构呢? Game Over!这类架构一定不要应用ReplicationFilter,只要应用ReplicationFilter,数据不一致就必不可免了。
个人的建议:
MGR对于每个MySQL的使用者,都或多或少的听过,或多或少的用过了,未知的Bug绝对超乎你的想象。所以,MGR使用时,在你无法掌控未知Bug导致的各种异常下,使用一定要谨慎。数据一致性校验,数据延迟校验一定一定要有的。
附加一个彩蛋:
- MySQL有一个参数:slave_parallel_workers.关于并行复制的。但该参数的调整,在传统Slave节点是需要stop & start slave sql_thread生效的。
- MGR中,该参数是作用在group_replication_applier的Channel中,机制和主从的并行复制基本一样。但该参数如何调整生效呢?
- 不要在stop group_replication and startgroup_replication了,关闭集群的操作太重了!
- 可以通过 stop slave sql_thread for channel 'group_replication_applier' , 然后start slave sql_thread for channel 'group_replication_applier' 即可生效。