先说现场
MySQL 源表已经有几千万行时,直接让 CDC 实时任务做全量快照,容易出现快照时间过长、源库压力升高和 binlog 消费延迟。更稳的做法是:普通任务负责存量,实时任务负责位点之后的变化。
方案怎么选
| 方案 | 适合场景 | 主要限制 |
|---|---|---|
| Canal | MySQL binlog 增量解析和消息分发 | 需要 MySQL、Kafka、消费端和位点维护配合 |
| Kettle | 批量抽取、转换和清洗 | 实时 CDC 和任务状态管理较弱 |
| DataX | 一次性离线全量迁移 | 缺少完整 Web 和 CDC 管理 |
| DataMover | 全量、增量字段和 CDC 的私有化同步 | 需要部署 Manager、Worker 和元数据库 |
大存量场景建议把全量和 CDC 分开,先用普通任务完成存量,再用实时任务追增量,避免直接快照带来的压力。
DataMover 是什么
DataMover 是一个私有化部署的数据迁移同步工具:
- 普通任务处理全量和基于增量字段的定时同步。
- 实时任务处理 MySQL CDC,通过 binlog 捕获 INSERT、UPDATE、DELETE。
- Web 界面配置数据源、表映射、字段映射、同步策略和执行监控。
- Manager 负责调度,Worker 负责实际读取和写入。
部署拓扑
浏览器
|
Manager: 8000
|
Worker: 8011
|
元数据库:MySQL 5.7+ 或 PostgreSQL 12+

curl -fsSL https://down.datamover.cn/install.sh | bash
下载页:https://datamover.cn/download.html
文档页:https://datamover.cn/doc/
准备阶段:测试表建表和造数
先在 MySQL 源端创建测试表并生成 1 万行数据。大存量验证可以在测试环境继续扩大到百万行,观察普通任务全量和实时任务位点衔接。
MySQL 源端测试表
CREATE TABLE dm_demo_user (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(64),
phone VARCHAR(32),
status VARCHAR(16),
amount DECIMAL(18,2),
created_at DATETIME,
updated_at DATETIME
);
INSERT INTO dm_demo_user (username, phone, status, amount, created_at, updated_at)
SELECT
CONCAT('user_', n),
CONCAT('1380000', LPAD(n, 4, '0')),
CASE WHEN n % 2 = 0 THEN 'active' ELSE 'inactive' END,
ROUND(RAND() * 100000, 2),
NOW(),
NOW()
FROM (
SELECT @n := @n + 1 AS n
FROM information_schema.columns a,
information_schema.columns b,
(SELECT @n := 0) c
LIMIT 10000
) t;
PostgreSQL 目标端预期表结构
CREATE TABLE dm_demo_user (
id BIGINT PRIMARY KEY,
username VARCHAR(64),
phone VARCHAR(32),
status VARCHAR(16),
amount NUMERIC(18,2),
created_at TIMESTAMP,
updated_at TIMESTAMP
);
源库和目标库权限
| 端 | 需要权限 | 原因 |
|---|---|---|
| MySQL 源端 | 读取表结构、业务数据和元数据;CDC 场景还要 binlog 读取权限 | 数据源连接、选表、字段映射和增量读取 |
| PostgreSQL 目标端 | 建表、写入、更新、删除 | 自动建表和任务写入 |
| 元数据库 | 创建数据库和表权限 | 保存任务、位点和执行记录 |
| Worker | 访问源端、目标端和元数据库 | 实际执行任务 |
MySQL CDC 前需要确认 binlog 已开启、行格式满足要求,并使用具备复制权限的账号。
MySQL 源端权限检测
SHOW GRANTS FOR 'datamover_user'@'%';
SELECT @@log_bin, @@binlog_format, @@binlog_row_image;
MySQL 源端授权示例
CREATE USER 'datamover_user'@'%' IDENTIFIED BY 'change_me';
GRANT SELECT, RELOAD, SHOW DATABASES, REPLICATION SLAVE, REPLICATION CLIENT
ON *.* TO 'datamover_user'@'%';
FLUSH PRIVILEGES;
PostgreSQL 目标端权限检测
SELECT grantee, table_schema, table_name, privilege_type
FROM information_schema.table_privileges
WHERE grantee = 'datamover_target'
ORDER BY table_name, privilege_type;
PostgreSQL 目标端授权示例
CREATE USER datamover_target WITH PASSWORD 'change_me';
CREATE SCHEMA datamover_sync AUTHORIZATION datamover_target;
GRANT ALL ON SCHEMA datamover_sync TO datamover_target;
DataMover 配置选择和内存配置
| 配置 | 建议 | 说明 |
|---|---|---|
| 普通任务全量 | 抽取方式选择全量 | 一次性同步存量 |
| 实时任务快照 | schema_only | 只记录位点,不执行存量快照 |
| offset JSON | 默认系统管理 | 不手写不确定位点 |
| 输出线程数 | 默认 1,逐步调 2 到 4 | 按目标端写入能力调整 |
| Worker JVM | 数据量大时调大 | 避免批大小提升后频繁 GC |
| 目标端索引 | 大批量迁移可评估迁移后再建索引 | 减少写入放大 |
大存量同步流程
- 创建普通任务,准备同步存量。
- 将普通任务复制成实时任务。
- 实时任务配置
schema_only,不进行快照。 - 启动并停止实时任务,确认已生成 offset。
- 启动普通任务,同步全部存量数据。
- 普通任务完成后,再次启动实时任务,从位点追增量。


字段映射重点
| MySQL 类型/特性 | PostgreSQL 处理 | 要确认什么 |
|---|---|---|
AUTO_INCREMENT | 序列或 identity | 当前值校准 |
TINYINT | SMALLINT | 状态和布尔字段 |
DATETIME | TIMESTAMP | 精度和时区 |
VARCHAR | VARCHAR | 长度、字符集 |
ON UPDATE | 时间戳逻辑单独确认 | 是否保留自动更新时间行为 |
结果验证
SELECT COUNT(*) FROM source_table;
SELECT COUNT(*) FROM target_table;
SELECT MIN(id), MAX(id) FROM source_table;
SELECT MIN(id), MAX(id) FROM target_table;
SELECT status, COUNT(*) FROM source_table GROUP BY status;
SELECT status, COUNT(*) FROM target_table GROUP BY status;
SELECT * FROM source_table WHERE id IN (1, 100, 1000);
SELECT * FROM target_table WHERE id IN (1, 100, 1000);
常见坑
位点先记录,但普通任务还没完成
普通任务未完成时启动实时任务,存量期间的变化会由实时任务补齐。重点确认普通任务完成状态和位点记录时机。
复制任务时目标表策略不清楚
实时任务配置不当可能清空目标表。设置 schema_only 时保持首次启动清空目标表关闭。
停止后重复消费
原因通常是 offset 被手动修改或任务重置。优先使用系统生成位点,重置前先确认目标表策略。