mysql之DTS的那些事
最近才考虑数据库迁移,想起了之前做DTS踩过的那些坑。
DTS同步binlog,开始是使用binlog event + position方式,之后追加支持了GTID。
基于数据库迁移,比如从源A库迁移到源B库,包括但不限于数据库上云。
数据库迁移方案有两种场景:
(1)、停机迁移方案【停服时间比较长】
这种方案是允许停服的场景,通过mysqldump就搞定了,就不说了。
(2)、在线不停机方案【最多只是切库的时间点,停服重部服务一下,停服时间很短。若不停服,就得想办法处理切为时间点的新产生的BINLOG】
这种场景方案中,我们采用先在线整库迁移,然后在通过binlog在线DTS对齐数据。
步骤如下:
1、源数据库采用ROW模式,开启binlog权限
2、需要一个源库的全局schema查询用户,获取源数据库的schema同步到目标库
3、选取某个时间点的BINLOG OFFSET做标记,然后通过JDBC同步整个库表数据到目标库,直至完毕。
4、通过netty服务单线程读取源库BINLOG数据,从上一步标记的offset位置开始读取,读入kafka。
5、多线程消费kafka数据到目标库,直至同步到最新的binlog数据,迁移完成。
第二种方案中遇到的那些坑:
1、最好选取源库的一个只读库做为同步数据的源库,这样不影响源库线上业务。另外开始同步整库时,需要选取当前Offset位置以备增量同步时使用,并且整库同步期间禁止写入或至少禁止修改schema操作(减少后面增量同步binlog时的程序报错,及异常表手动处理的成本)。
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、同步服务的效率和源库、目标库的网络带宽,数据库配置息息相关
9、由于业务在正常的运转的,需要找个时间点校验数据的完整性,在业务流量低时,手动停止同步,线上服务切到新库,(这样需要处理切库时的binlog,最好短时停服切库)
10、一旦开始同步,在手动停止同步之前,不能修改DDL,否则会导致同步任务失败
11、存储过程及视图不会同步,需要切库后,手动处理
备注:
1、 GTID最初由google实现,MySQL 从5.6.5 新增了基于 GTID 的复制方式。通过 GTID 保证了每个在主库上提交的事务在集群中有一个唯一的ID。这种方式强化了数据库的主备一致性,故障恢复以及容错能力。GTID (Global Transaction ID)是全局事务ID,当在主库上提交事务或者被从库应用时,可以定位和追踪每一个事务。
2、查看当前的Binlog最终偏移量方法
## 获取binlog文件列表,找到最新的binlog文件
mysql> show binary logs;
mysql> show binlog events in 'binlog.0000MAX'; ##查来下面的End_log_pos,就是最新的binlog偏移量了
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info