最近才考虑数据库迁移,想起了之前做DTS踩过的那些坑。
DTS同步binlog,开始是使用binlog event + position方式,之后追加支持了GTID。
基于数据库迁移,比如从源A库迁移到源B库,包括但不限于数据库上云。
数据库迁移方案有两种场景:
(1)、停机迁移方案
这种方案是允许停服的场景,通过mysqldump就搞定了,就不说了。
(2)、在线不停机方案
这种场景方案中,我们采用先在线整库迁移,然后在通过binlog在线DTS对齐数据。
步骤如下:
1、源数据库采用ROW模式,开启binlog权限
2、需要一个源库的全局schema查询用户,获取源数据库的schema同步到目标库
3、选取某个时间点的BINLOG OFFSET做标记,然后通过JDBC同步整个库表数据到目标库,直至完毕。
4、通过netty服务单线程读取源库BINLOG数据,从上一步标记的offset位置开始读取,读入kafka。
5、多线程消费kafka数据到目标库,直至同步到最新的binlog数据,迁移完成。
第二种方案中遇到的那些坑:
1、最好选取源库的一个只读库做为同步数据的源库,这样不影响源库线上业务
2、多线程消费kafka时,容易出现binlog顺序错乱的问题,目前采用按表写partition的方式,指定partitions消费,避免顺序错乱,但带来的新问题就是kafka的各partitions数据倾斜问题。
3、目前解析binlog同步数据时,DDL和DML操作没有特殊分别处理,如果数据量比较 大时,DDL很容易超时,导致此DDL之后同步的binlog都有问题,需要重新同步
4、同步binlog时,指定时间窗口大小,记录同步时的binlog位置到zk上,如果需要重新同步数据,可能会导致一部分binlog重复同步。如果窗口过小,zk也扛不住
5、遇到没有主键或唯一性限制的表,重复同步,会导致数据重复
6、若遇到同步blob相关类型时,若二进制数据过大,可能导致同步失败
7、同步服务的部署问题,源库和目标库都需要开公网IP。
8、同步服务的效率和源库、目标库的网络带宽,数据库配置息息相关
备注:
GTID最初由google实现,MySQL 从5.6.5 新增了基于 GTID 的复制方式。通过 GTID 保证了每个在主库上提交的事务在集群中有一个唯一的ID。这种方式强化了数据库的主备一致性,故障恢复以及容错能力。GTID (Global Transaction ID)是全局事务ID,当在主库上提交事务或者被从库应用时,可以定位和追踪每一个事务。