
简介dbswitch是一款面向数据库开发与运维人员的批量迁移同步工具用于解决源端数据库向目的端数据库的结构与数据搬迁问题适合需要跨库整库迁移、表结构转换及增量变更同步的技术场景。资源包共506个文件约99.09MB以306个java源码为核心辅以36个js、25个vue构成的前端界面20个jar依赖、15个xml与6个yml配置、13个sql脚本以及9个sh、4个cmd启动脚本和Dockerfile等部署文件整体工程结构完整便于二次开发与本地运行。功能上支持字段类型、主键信息与建表语句的转换并生成建表SQL可基于正则表达式完成表名与字段名映射数据同步采用JDBC分批次读取并以insert/copy方式分批写入目的库同时支持有主键表的增量变更同步变化数据计算千万级以上数据量的性能仍需在生产环境验证。目前已有793人学习下载适合数据库开发包使用者参考借鉴。1. 异构数据库批量迁移为什么“全量增量”才是真需求做过数据迁移的人多半有过这种经历源端和目标端是两种不同的数据库表结构要转、字段类型要映射、数据要搬搬完之后业务还不能停增量数据得持续追平。dbswitch 这类工具瞄准的就是这个场景——把源端数据库的数据批量迁移同步到目的端数据库同时支持全量和增量两种方式。它不是简单的导出导入而是要在异构环境里解决方言差异、类型映射、断点续传和增量捕获这几件事。适合谁用一是手上有多套异构数据库、需要做数据整合的团队二是做信创替换、需要把业务数据从一种库平滑搬到另一种库的工程师三是需要定期做跨库数据同步、又不想写一堆胶水代码的开发者。全量解决“存量怎么搬过去”增量解决“搬完之后新数据怎么持续跟上”两者配合才构成一条完整的迁移链路。下面从选型、配置、实操到避坑把这条路走一遍。2. 全量迁移的落地路径从建表到数据校验2.1 先搞清楚全量迁移到底在做什么全量迁移的核心动作可以拆成四步读源端元数据、在目标端建表、批量搬数据、校验一致性。dbswitch 在这四步里做的事本质是一层“翻译搬运”的中间层。它连接源端和目标端把源端的表结构按目标端的方言重新表达再把数据按批次读出来写进去。这里有个容易被忽略的点全量不是“一次性把所有数据读进内存再写”。真实场景里表可能有几千万行必须分批。dbswitch 一般按 fetchSize 控制每次从源端读取的行数再按 batchSize 控制每次写入目标端的行数。这两个参数设不好要么内存爆要么网络往返次数太多导致慢得离谱。另一个关键点是建表策略。异构迁移时源端的 varchar(255) 到了目标端可能得变成 varchar2(255) 或者 text源端的 datetime 到了目标端可能是 timestamp。dbswitch 内置了类型映射规则但不同数据库组合的映射不一定完全符合你的预期所以建表前最好先看一眼它生成的 DDL。2.2 配置一个全量迁移任务以常见的“源端 MySQL 到目标端 PostgreSQL”为例配置通常分三块数据源定义、迁移任务定义、执行参数。下面是一个典型的配置片段用 YAML 表达不同版本配置格式可能不同以实际为准# 数据源定义源端 MySQL source: type: mysql url: jdbc:mysql://source-host:3306/biz_db?useSSLfalseserverTimezoneAsia/Shanghai username: migrator password: ****** driver: com.mysql.cj.jdbc.Driver # 数据源定义目标端 PostgreSQL target: type: postgresql url: jdbc:postgresql://target-host:5432/biz_db username: migrator password: ****** driver: org.postgresql.Driver # 迁移任务 task: name: full_migrate_biz mode: full # 全量模式 sourceSchema: biz_db targetSchema: public tables: - order_info - user_profile - product_catalog fetchSize: 5000 # 每次从源端读取行数 batchSize: 1000 # 每次写入目标端行数 createTable: true # 目标端不存在时自动建表 dropTable: false # 是否先删目标表首次迁移设 false threadCount: 4 # 并发线程数这段配置里几个参数值得展开说。fetchSize 设 5000 意味着 JDBC 驱动每次从 MySQL 拉 5000 行到客户端内存太小会导致频繁网络交互太大会占内存。batchSize 设 1000 意味着每攒够 1000 行就往 PostgreSQL 发一次 insert这个值受目标端 max_allowed_packet 或类似参数限制不是越大越好。threadCount 控制并发迁移的表数量不是单表内的并发所以表多的时候可以调大表少的时候调大反而增加锁竞争。createTable 为 true 时dbswitch 会根据源端表结构生成目标端 DDL。这里有个血泪经验自动生成的 DDL 不一定带索引和主键如果业务对查询性能有要求迁移完得手动补索引。dropTable 在首次迁移时一定要设 false否则目标端已有同名表会被清空这个操作没有后悔药。2.3 执行迁移并观察进度配置写好后执行方式取决于 dbswitch 的部署形态。如果是命令行工具通常是# 执行全量迁移任务 dbswitch-cli --config /path/to/migrate-config.yaml --task full_migrate_biz # 查看任务状态 dbswitch-cli --status --task full_migrate_biz执行过程中要盯几个指标已迁移行数、当前速率、是否有报错。dbswitch 一般会输出日志关键日志包括“开始迁移表 X”“表 X 迁移完成共 N 行”“表 X 迁移失败原因...”。如果某张表失败先看是不是类型不兼容比如源端有 JSON 字段而目标端版本不支持或者源端有 unsigned bigint 而目标端没有对应类型。迁移完成后必须做数据校验。最简单的办法是对每张表做行数比对-- 源端 SELECT COUNT(*) FROM order_info; -- 目标端 SELECT COUNT(*) FROM order_info;行数一致不代表数据完全一致但行数不一致一定有问题。更严格的校验可以做分片 checksum比如按主键区间取每段的 MD5 值比对。dbswitch 有些版本内置了校验功能如果没有自己写个脚本按主键分段比对也不难。3. 增量同步的落地路径从捕获到追平3.1 增量同步的三种常见实现思路增量同步要解决的核心问题是“怎么知道源端哪些数据变了”。常见做法有三种基于时间戳、基于触发器、基于日志解析。基于时间戳最简单要求源端表有 update_time 或类似字段每次同步时只取上次同步时间之后变更的数据。缺点是删除操作捕获不到而且如果业务写入时没有维护时间戳这条路走不通。基于触发器是在源端表上挂触发器把变更写到一个中间表同步工具读中间表。优点是能捕获所有变更类型缺点是对源端有侵入高并发写入时触发器会成为瓶颈。基于日志解析是侵入最小的方式通过解析数据库的 binlog 或 WAL 日志来获取变更。dbswitch 的增量能力通常依赖这种方式因为它不需要改表结构对业务透明。但日志解析对数据库配置有要求比如 MySQL 要开 binlog 且格式为 ROWPostgreSQL 要开 logical replication。3.2 配置增量同步任务增量任务的配置和全量类似但多了几个关键参数task: name: incr_sync_biz mode: incremental # 增量模式 sourceSchema: biz_db targetSchema: public tables: - order_info - user_profile # 增量起点从某个时间点或某个位点开始 startPosition: 2025-01-01 00:00:00 # 冲突处理策略目标端已存在相同主键时怎么办 conflictStrategy: upsert # 可选 insert / update / upsert / skip # 批量提交间隔毫秒 flushInterval: 1000 # 每次批量写入行数 batchSize: 500conflictStrategy 是增量同步里最容易翻车的地方。如果设成 insert目标端已有相同主键就会报错设成 update如果目标端没有这条记录就会丢数据upsert 是最稳妥的但要求目标端支持 upsert 语法MySQL 的 ON DUPLICATE KEY UPDATE、PostgreSQL 的 ON CONFLICT。skip 适合只追加不更新的场景。startPosition 决定从哪个位点开始追增量。如果是第一次做增量通常从全量迁移完成的时间点开始如果是断点续传就从上次记录的位点开始。dbswitch 一般会把同步位点持久化到一张元数据表里重启后自动从上次位点继续。3.3 增量追平的验证方法增量同步配好之后怎么确认它真的在工作最直接的办法是在源端插一条数据等几秒去目标端查-- 源端插入 INSERT INTO order_info (order_id, user_id, amount, status, update_time) VALUES (999999, 1001, 88.50, paid, NOW()); -- 等待同步延迟后目标端查询 SELECT * FROM order_info WHERE order_id 999999;如果目标端能查到说明增量链路通了。再测更新和删除-- 源端更新 UPDATE order_info SET status shipped WHERE order_id 999999; -- 源端删除 DELETE FROM order_info WHERE order_id 999999;更新和删除都能正确同步到目标端才算增量链路完整。这里要注意基于日志解析的方案对删除的捕获依赖 binlog 的 ROW 格式和 full 镜像配置如果 binlog 只记了主键没记完整行删除同步可能只能删主键匹配的行这个在配置阶段就要确认好。4. 避坑与排查那些让迁移任务翻车的细节4.1 类型映射不对导致建表失败或数据截断现象全量迁移时目标端建表报错或者数据写进去之后发现字符串被截断、小数精度丢失。原因不同数据库的类型系统差异比想象中大。比如 MySQL 的 TEXT 到了 Oracle 可能得用 CLOBMySQL 的 DATETIME 到了 PostgreSQL 是 TIMESTAMPMySQL 的 TINYINT(1) 在有些工具里被映射成 BOOLEAN 有些映射成 SMALLINT。dbswitch 的默认映射规则不一定覆盖所有边界情况。解决迁移前先跑一遍“只建表不搬数据”的 dry-run把生成的 DDL 导出来人工审一遍。重点看 varchar 长度、decimal 精度、时间类型、大字段类型。发现不对就在配置里加类型映射覆盖规则或者手动改完 DDL 再让工具跳过建表步骤。4.2 增量同步延迟越来越大现象刚开始增量同步延迟只有几百毫秒跑了一段时间后延迟涨到几分钟甚至几十分钟且不回落。原因常见的有三种。一是源端写入量突增同步工具消费速度跟不上二是目标端写入变慢比如目标端在做大批量查询导致锁等待三是同步工具内部队列积压通常是 batchSize 设得太小导致频繁提交或者 flushInterval 太长导致数据攒着不写。解决先看同步工具的监控指标确认瓶颈在读取端还是写入端。如果是读取端慢调大 fetchSize 和并发数如果是写入端慢检查目标端是否有锁竞争或磁盘 IO 瓶颈如果是队列积压调大 batchSize 并适当减小 flushInterval。另外增量同步期间尽量避免在目标端跑大查询尤其是全表扫描。4.3 全量迁移到一半断了重跑时数据重复现象全量迁移因为网络抖动或源端连接超时中断重新执行后目标端出现重复数据。原因全量迁移如果没有做幂等处理重跑时会把已经迁过的数据再插一遍。dbswitch 有些模式支持断点续传但断点续传依赖位点记录如果位点没持久化或者持久化不及时重跑就会从头开始。解决全量迁移前先确认工具是否支持断点续传如果支持确保位点存储是可靠的比如写到独立的元数据库而不是内存。如果不支持断点续传重跑前先清空目标表或者用 truncate insert 的方式。更稳妥的做法是全量迁移时开启 upsert 模式这样重跑不会产生重复数据但会牺牲一些写入性能。4.4 源端表结构变更导致同步中断现象增量同步正常运行中突然报错日志显示“column not found”或“schema mismatch”。原因源端做了 DDL 变更比如加了一列、删了一列、改了列类型而同步工具还在用旧的表结构定义去解析数据。解决增量同步期间源端尽量避免 DDL 变更。如果必须变更变更后需要重启同步任务并刷新元数据。有些工具支持自动感知 schema 变更但异构场景下自动适配不一定可靠手动介入更稳妥。长期方案是建立变更管理流程DDL 变更前先暂停同步变更完成后重新初始化增量链路。4.5 目标端主键冲突导致增量数据丢失现象增量同步日志里出现大量“duplicate key”错误部分数据没有同步到目标端。原因conflictStrategy 设成了 insert但目标端已经存在相同主键的记录。这种情况常见于全量迁移和增量同步切换时位点没对齐或者目标端有其他写入源在同时写数据。解决把 conflictStrategy 改成 upsert让目标端在冲突时执行更新而不是报错。如果目标端不支持 upsert可以先 delete 再 insert但这有短暂的数据空洞期。另外要检查全量迁移完成的时间点和增量起始位点是否对齐避免重复消费或漏消费。5. 进阶技巧让迁移任务更可控的几个习惯5.1 用分片并行加速大表全量迁移单张大表全量迁移时单线程读写的速度往往上不去。一个实用技巧是按主键区间把大表拆成多个分片每个分片独立迁移。dbswitch 如果支持分片配置可以这样设task: name: full_migrate_big_table mode: full tables: - table: order_detail splitColumn: order_id # 按此列分片 splitSize: 1000000 # 每个分片100万行 threadCount: 8 # 分片并发数splitColumn 要选分布均匀的数值列或时间列splitSize 根据单表总行数和目标端承载能力来定。分片迁移的注意点是如果迁移过程中源端还在写入分片边界可能会有数据漂移所以分片迁移更适合配合增量同步一起用——先分片搬存量再用增量追平差异。5.2 迁移前后的数据校验脚本行数比对只是最粗的校验。更可靠的做法是按主键分段做 checksum。下面是一个简化版的 Python 校验脚本思路import hashlib def segment_checksum(conn, table, pk_col, start, end): 计算指定主键区间内数据的校验和 sql fSELECT {pk_col}, MD5(CONCAT_WS(|, ...)) FROM {table} \ fWHERE {pk_col} {start} AND {pk_col} {end} ORDER BY {pk_col} cursor conn.cursor() cursor.execute(sql) md5 hashlib.md5() for row in cursor: md5.update(str(row).encode()) return md5.hexdigest() # 对源端和目标端分别计算相同区间的 checksum比对是否一致 # 不一致的区间再细查具体行这个脚本的关键是 CONCAT_WS 里要把所有业务字段拼进去并且源端和目标端的拼接顺序、NULL 处理方式要一致。校验通过不代表 100% 没问题但校验不通过一定有问题能帮你快速定位到具体哪个主键区间出了偏差。5.3 迁移窗口和回滚预案不管工具多成熟迁移前都要准备好回滚预案。最基本的几条迁移前对目标端做一次全量备份迁移期间源端尽量只读或低峰写入迁移完成后先跑一段时间双写或比对确认无误再切流量。如果迁移中途发现严重问题回滚方案要能快速把业务切回源端而不是在现场调试迁移工具。我自己的习惯是任何一次生产迁移先在测试环境用同等数据量跑一遍全流程记录每个阶段的耗时和报错。测试环境跑通了生产环境才动手。迁移当天不开新任务专注盯这一件事。增量同步的延迟监控要设告警延迟超过阈值就人工介入别等业务反馈数据不对才去查。希望帮到你。本文还有配套的精品资源点击获取