共计 1797 个字符,预计需要花费 5 分钟才能阅读完成。
最近处理了一个迁移阿里云PolarDB和ApsaraDB RDS的需求,其实就是MySQL。
数据迁移的核心是数据同步任务(Data Transfer Service)的设置,通过该工具了解了数据库迁移的一些底层逻辑。
在DTS设置里决定同步哪些对象,这是基础部分:
- 表
- 视图
- 函数
- 存储过程
接下来会踩到两个坑:
①. 第1个坑是binlog_expire_logs_seconds参数的设置(MySQL 8.0,在MySQL 5.5+里则是expire_logs_days),需要确保全量同步任务在这个参数的期限内完成。在DTS任务迁移过程中会读取启动时候保存的binlog位点(GTID)数据,如果在读取时发现最初的binlog位点已经被清理掉,而从后续现存位点接续同步,会导致中间部分的丢失。下面是该过程的示意图:

如图所示,如果只保存3天的binlog,同步任务是8/2启动,如果8/4完成,则DTS可以读取到最初的binlog位点并开始记录增量操作;如果8/6才完成,旧binlog已经被清理了,8/2-8/4之间的操作记录就丢失了。
什么是binlog:是 MySQL 在服务层记录所有会引起数据或结构变化的事件的日志,用于复制、恢复与审计等场景;它不会记录 SELECT/SHOW 等纯读操作。binlog文件结构示例:
Position | Event Type | Timestamp | Details |
---|---|---|---|
4 | Format_description_event | 2025-01-15 10:00:01 | MySQL 8.0.32 server_version, binlog_format=ROW |
126 | Previous_gtids_event | 2025-01-15 10:00:01 | gtid_set: empty |
157 | Anonymous_Gtid_event | 2025-01-15 10:30:15 | ANONYMOUS |
228 | Query_event | 2025-01-15 10:30:15 | BEGIN |
297 | Table_map_event | 2025-01-15 10:30:15 | Table: test_db.users, table_id: 108 |
378 | Write_rows_event | 2025-01-15 10:30:15 | INSERT: id=1, name=’alice’, age=25 |
445 | Xid_event | 2025-01-15 10:30:15 | COMMIT xid=12345 |
476 | Anonymous_Gtid_event | 2025-01-15 10:32:22 | ANONYMOUS |
547 | Query_event | 2025-01-15 10:32:22 | BEGIN |
616 | Table_map_event | 2025-01-15 10:32:22 | Table: test_db.users, table_id: 108 |
697 | Update_rows_event | 2025-01-15 10:32:22 | UPDATE: WHERE id=1 SET age=26 |
786 | Xid_event | 2025-01-15 10:32:22 | COMMIT xid=12346 |
817 | Anonymous_Gtid_event | 2025-01-15 10:35:10 | ANONYMOUS |
888 | Query_event | 2025-01-15 10:35:10 | BEGIN |
957 | Table_map_event | 2025-01-15 10:35:10 | Table: test_db.users, table_id: 108 |
1038 | Delete_rows_event | 2025-01-15 10:35:10 | DELETE: WHERE id=1 |
1105 | Xid_event | 2025-01-15 10:35:10 | COMMIT xid=12347 |
1136 | Rotate_event | 2025-01-15 11:00:00 | Next log: mysql-bin.000002 position: 4 |
② 第2个坑则是在公版MySQL中binlog_expire_logs_seconds设置为0是永不过期的,但是在PaaS版中,这个值如果是0,云厂商(比如Azure)可能会在后台过几小时自动清理。所以在DTS任务中,需要给该参数一个实际的值。另一种情况是比如阿里云ApsaraDB RDS,该参数不能直接设置,需要实例的日志备份中单独设置。
最后一点,将同步任务拆分成多个表并行处理,可以有效避免一次性同步遇到意外而需要完全从头开始浪费的时间。