
副标题一个基于 RuoYi-Vue 二次开发的轻量级 ETL 平台专治DBA 跑路 / DataX 配错 / Canal 命令行劝退。一、为什么要造这个轮子我们团队过去三年踩过太多次坑场景现状痛点业务库拆分订单库 → 订单中台库用 DataX 写 JSON字段映射要手写 joiner运维同事上手成本高实时订阅 binlog部署 Canal 写 Kafka 消费要懂 canal 协议 位点 多线程 ack错一次就丢数据DBA 离职交接几个脚本散落在跳板机新人接手无从下手权限审计一塌糊涂临时数据修复程序员手动INSERT ... SELECT容易把生产主键写崩且没日志于是就有了DataMove——把数据同步做成配置即任务选源库 → 选目标库 → 选表 → 点启动再在浏览器里看日志、收钉钉告警。项目代码完全开源二级拿到手就能直接用。在线体验http://8.140.200.84/官网http://8.140.200.84/website/二、它能做什么┌────────────────────────────────────────────────────────────┐ │ DataMove 能力地图 │ ├──────────────┬─────────────────────────────────────────────┤ │ 数据源 │ MySQL 5.7 / 8.x多源并存密码 AES 加密存储 │ │ 全量同步 │ 按主键 ID / 按时间字段断点续传、幂等覆盖 │ │ 增量同步 │ 基于 Canal 1.1 订阅 binlog自动 ACK 位点 │ │ SQL 工作台 │ CodeMirror 编辑器多语句、CtrlEnter 执行 │ │ 数据浏览 │ 在线分页浏览任意已注册数据源带行数统计 │ │ 同步日志 │ 批次明细 总进度支持 CSV 导出 │ │ 告警 │ 钉钉 Webhook 主动推送启动失败/中断/对账异常│ │ 授权 │ MAC LicenseKey 一机一绑离线可用 │ │ 权限 │ admin / operator 两级 RBAC │ └──────────────┴─────────────────────────────────────────────┘对比 DataX / Canal-adapter / DTS 这些老炮DataMove 的优势是零代码 全中文 自带可视化 自带授权适合中小团队开箱即用。三、整体架构前端 (Vue 2 Element UI)后端 (SpringBoot 2.7)存储基础设施HTTP / SwaggerJDBC 分批TCP 11111订阅 ROW binlog数据源/任务/日志SQL 工作台Controller 层数据源服务任务服务FullSyncEngine全量引擎CanalSyncEngine增量引擎SQL 引擎License 服务SyncLogService异步日志钉钉告警MySQL 8.0元数据 业务RedisToken 缓存Canal Server订阅 binlog核心模块仅 ~4 个 Java 包com.ruoyi.datamove ├── datasource // 数据源管理 ├── task // 同步任务 CRUD ├── engine │ ├── full // FullSyncEngine (断点续传 幂等) │ ├── incr // CanalSyncEngine (增量 位点 ACK) │ └── log // SyncLogService (批次明细) ├── browse // 在线浏览数据 ├── license // 离线授权校验 └── log // 日志导出 controller四、关键技术点 1全量同步的双引擎 断点续传 幂等4.1 两种同步模式模式适用场景WHERE 片段按主键 ID几乎所有业务表WHERE id #{lastId} LIMIT #{batchSize}按时间字段没有自增主键的表 / 日志型表WHERE time #{lastTime} OR (time #{lastTime} AND id #{lastIdInBatch})按时间模式里同秒数据的处理是关键先用time #{lastTime} AND id #{lastIdInBatch}把同秒内剩余行捞完再推进lastTime彻底解决漏数据 / 重复拉取。4.2 断点续传的核心原则整批 INSERT 成功 → 才更新lastSyncMaxId/lastSyncTime伪代码while (有下一批) { rows selectByCondition(lastId); try { tx.begin(); batchInsertOrUpdate(rows); // ON DUPLICATE KEY UPDATE updateProgress(lastId rows.lastId); // ✅ 仅成功才推进 tx.commit(); } catch (Exception e) { tx.rollback(); // 下次启动会从 lastId 重新拉这一批 } }崩溃重启自动从上次lastSyncMaxId继续不会丢也不会重复。重复执行安全INSERT ... ON DUPLICATE KEY UPDATE是 MySQL 幂等标准写法。4.3 整批ON DUPLICATE KEY UPDATE而不是REPLACE INTOREPLACE会先DELETE旧行对带AUTO_INCREMENT的表会改主键、并触发级联删除ON DUPLICATE KEY UPDATE只 update 既有列幂等且不破坏外键。五、关键技术点 2Canal 增量同步 位点 ACK5.1 同步流程启动 → CanalConnector.connect() → subscribe(filter) → 循环 getWithoutAck(1000) ↓ apply(CanalEntry) → JDBC applyRowData() ↓ getAck(batchId) // ✅ 处理成功才 ack ↓ 更新 sync_canal_position 表5.2 反向回环防护源端写入的目标库也会产生 binlog会被 Canal 误二次同步。 DataMove 用库名白名单 任务级 destination两层过滤Canal 配置里只订阅datamove库的data_move_test表精确过滤。每个任务绑定独立destination一个任务一个订阅通道。5.3 失败回滚try { apply(events); // 写目标库 connector.ack(batchId); // ✅ 推进位点 } catch (Exception e) { connector.rollback(batchId); // ❌ 不 ack下次重做 sync_canal_position 不更新; 触发钉钉告警; }关键设计位点更新必须在ack之后否则一旦程序在 update position 前崩溃重启会丢事件。七、关键技术点 3SQL 工作台运维救场神器数据同步之外DataMove 还附带一个 Web 版的 SQL 工作台CodeMirror 6 编辑器支持 MySQL 关键字高亮 智能补全Ctrl Space。多语句执行按分号拆分每个语句单独展示结果。查询结果 1000 行上限超过提示可一键导出Excel / CSV。Ctrl Enter执行当前选中或全部效率直逼本地 Navicat。操作历史每次执行保留在页面内点 tag 可回填到编辑器。DBA 哥哥再也不用远程登录服务器开 SSH 隧道了。八、同步日志批次级粒度 CSV 导出SyncLogService会在每个批次结束后异步写入sync_task_log字段含义task_id任务 IDtask_name任务名sync_modeFULL / INCRbatch_no批次号增量任务记录 binlog 起止位点start_key/end_keybatch_rows本批处理行数total_rows累计已同步行数cost_ms本批耗时statusSUCCESS / FAILEDerror_msg失败信息FAILED 时填全量任务批次号天然递增。增量任务批次号 canal message batchIdstart_key/end_key是binlog:offset让管理员一眼能定位到具体 binlog 位置。支持按任务 ID、状态筛选一键 CSV 导出字段含start_key / end_key供运维追溯。十、告警钉钉 Webhook 主动推送触发场景推送内容任务启动失败 / 数据源连不上[DataMove告警] 任务[xxx] 启动失败: 源库连接失败全量中断 / 增量 binlog 断开[DataMove告警] 任务[xxx] 已中断, 请查看日志单批次错误率超过阈值[DataMove告警] 任务[xxx] 失败 N 条, 错误样本: ...每条任务支持独立 Webhook运维在钉钉群里就能秒级响应。十一、十分钟跑起来# 1. 初始化 MySQL mysql -uroot -p sql/datamove.sql # 2. 启动后端 mvn clean package -DskipTests java -jar target/datamove.jar # → Swagger 文档: http://localhost:8080/swagger-ui/index.html # 3. 启动前端 cd ruoyi-ui npm install npm run dev # → http://localhost:80 账号 admin / admin123 # 4. 可选Docker 起 Canal docker compose -f docker/canal/docker-compose.yml up -d首次登录后 4 步即可同步授权管理→ 确认 License 状态首次启动自动 30 天试用。数据源→ 添加源库与目标库 → 点 测试连接。任务→ 新建任务全量或增量→ 点 启动 → 在 同步日志 看实时进度。钉钉→ 在任务里填 Webhook → 异常自动推送到钉钉群。十二、安全与权限密码 / LicenseKey / 数据源密码全部入库前 AES 加密。前端回显只显示前 2 位 **** 后 2 位明文绝不出现。Spring Security JWT路由级权限。内置两种角色admin全权可改 License、可改数据源密码。operator仅查看任务、启停任务、看日志零数据源操作权限。admin默认密码首次登录强制修改。十三、性能与稳定性经验JDBC 批写 1000 行/批经测试addBatch executeBatch比单条 INSERT 快 50~80 倍1000 行是吞吐与事务回滚成本的甜点。setFetchSize(batchSize)MySQL 驱动必须显式设才能流式取否则会一次性把所有数据塞进内存OOM 重灾区。Canal 失败回滚见上文 §5.3。钉钉限流批量失败不并发推最多保留最近 5 条事件避免被风控。十四、Roadmap二期规划[ ] DDL 同步库表结构变更自动跟随[ ] 多线程极速同步按主键区间分片并行[ ] 数据差异对账 一键修复[ ] 数据脱敏手机号 / 身份证 / 邮箱[ ] PostgreSQL / Oracle / 达梦支持[ ] SaaS 多租户 Web 版十五、写在最后DataMove 不是一个万能 ETL 平台它的定位非常清晰给中小企业 / 个人 / 外包团队的零代码 MySQL 同步工具。如果你正被 DataX JSON 折磨、被 Canal 命令行劝退、被 DBA 离职搞得焦头烂额不妨试试gitee : https://gitee.com/qingtian2023/datamove.git文档README.md Swagger UI 一站式反馈欢迎提 Issue / PR如果你觉得这个项目有帮助欢迎Star ⭐鼓励一下作者这也是开源最大的动力。