Dbsyncer这名字我也是在项目群里看人提过几次,正好手头有个MySQL同步到MySQL的需求,就拿来试了一周。先说结论:对于“mysql to mysql 增量、全量”这种最常见的同步场景,Dbsyncer能省掉你一大半手工脚本的功夫,而且自带管理界面,不用写代码就能配完整个流程。这篇文章就围绕它的部署、驱动配置、全量同步、增量同步这四个关键点展开,把我的实操过程、参数选择和踩过的坑都整理出来,给想用它的人一份能直接照着干的参考。
1. 数据同步的选型思路与Dbsyncer的定位
1.1 为什么需要数据同步中间件
很多团队一开始做数据同步,走的是“业务代码双写”或者“定时导数据”的路子。代码双写侵入性太强,每个写操作都要多一次网络开销,而且在事务里处理不好就容易出现一端成功一端失败的情况,排查起来特别痛苦。定时导数据(比如凌晨跑个脚本把A库数据刷到B库)倒是简单,但实时性基本为零,业务一旦要求“数据变更后几秒内能看到”,这种方式就直接废了。
所以就有了基于日志解析的增量同步方案。MySQL把每一次数据变更记录到binlog里,同步工具伪装成一个从库去读binlog,再解析出增删改操作,转发到目标端。这套机制对源库几乎没有侵入,不用改业务代码,也不会增加事务负担。Dbsyncer走的就是这个路子,同时在全量同步这块又做了一层封装,把“先全量拉基线、再增量补变化”的常见同步策略合并成了一个可视化配置流程。
1.2 Dbsyncer的核心组件与同步机制
Dbsyncer是开源的数据同步中间件,源码在Gitee和GitHub上都能找到。它主要由这么几块组成:
- 管理控制台:一个Web界面,负责管理数据源、同步器、同步任务和日志。
- 数据源管理:统一管理源端和目标端连接,目前支持MySQL、Oracle、SqlServer、PostgreSQL等数据库,以及Elasticsearch、Kafka等存储。
- 同步器:定义“怎么读”和“怎么写”的规则。常见的如表同步器,允许你指定源表、目标表、字段映射和过滤条件。
- 任务调度:按频率或者手动触发同步任务,支持定时同步、增量监听。
- 日志模块:记录每次同步的详细日志,能看同步速度、错误信息、断点位置。
全量同步的机制本质上是JDBC分批查询。控制台按你配置的chunk大小,比如每批5000行,从源表批量SELECT出来,再批量写入目标表。这个过程可以手动触发,也可以按cron表达式定时执行。增量同步则完全不同,它是通过解析binlog事件流来感知数据变化,源库每产生一条INSERT/UPDATE/DELETE,目标库就会收到对应的变更操作,延迟控制在秒级。
1.3 和其他工具的对比:什么时候选它
说到数据同步中间件,大家可能还听过Canal、DataX、Flink CDC这些名字。简单做个横向对比,方便你判断场景是否匹配。
| 工具 | 增量同步 | 全量同步 | 界面化管理 | 上手成本 |
|---|---|---|---|---|
| Canal | 强项,主打binlog订阅 | 不支持,需配合其他工具 | 一般,需要自研客户端或连第三方平台 | 中 |
| DataX | 不支持 | 强项,离线批量导入 | 无,纯命令行 | 中 |
| Flink CDC | 强项,支持断点续传 | 支持,但需要写Flink作业 | 无,需要开发能力 | 高 |
| Dbsyncer | 支持,基于binlog | 支持,可视化配置 | 有,开箱即用 | 低 |
如果你对实时性要求极高、且团队有Java和Flink开发能力,Flink CDC依然是工业级首选。但多数做内部系统、报表库、运营数据平台的团队,其实要的就是“几分钟搭好一条同步链路”。Dbsyncer最适合的场景就是:不想写代码、不想维护一堆客户端脚本、需要一个界面能看日志和监控、并且同步链路以MySQL为中心。它对标的就是这种轻量级、可视化、可维护的定位。
2. 环境准备与部署安装
2.1 环境要求一览
先把环境要求放在前面,免得后面折腾半天发现基础条件不满足。
| 依赖项 | 版本/要求 | 说明 |
|---|---|---|
| JDK | 1.8及以上 | Dbsyncer基于Java开发,控制台和同步引擎需要JVM |
| MySQL 源端 | 5.6/5.7/8.0 | 必须开启binlog,详见2.3 |
| MySQL 目标端 | 5.6及以上 | 目标库没有特殊要求,建好表即可 |
| 内存 | 建议2G以上 | 增量任务长时间运行,JVM堆外内存占用会涨 |
| 存储 | 数据目录至少预留几GB | 用于存内置H2库、日志文件、同步断点等 |
我用的是CentOS 7服务器,MySQL 5.7源库、MySQL 5.7目标库,JDK 1.8,内存4G,整个流程跑下来很顺畅。
2.2 下载、解压与启动
Dbsyncer的安装包在官网和Gitee Releases里都有发布。下载下来是zip或tar.gz包,解压后目录结构比较简洁:
dbsyncer/ ├── bin/ │ └── startup.bat / startup.sh ├── conf/ ├── lib/ └── logs/启动前先确保JDK环境正常:
java -version启动直接执行:
cd bin ./startup.shWindows下双击startup.bat即可。启动成功后,控制台默认端口是7860,浏览器访问http://服务器IP:7860就能打开登录页。默认账号密码通常是admin / admin,首次登录后建议立刻修改,这属于基本操作。
注意:
bin目录下的脚本会读取conf里的配置来决定运行端口和数据目录,具体以你下载版本的实际文档为准。改端口的话,找到配置文件里关于端口的内容改掉重启就行。
2.3 MySQL源端参数准备(关键一步)
增量同步依赖binlog,所以源库必须开启binlog。这是我第一次使用时忽略的环节,导致增量任务一直监听不到数据变化。原因是MySQL默认在很多发行版上log_bin是关闭的。开启步骤:
登录MySQL,查看当前binlog配置:
show variables like 'log_bin'; show variables like 'binlog_format';如果log_bin是OFF,需要修改MySQL配置文件。Linux下通常是/etc/my.cnf,Windows下是my.ini。在[mysqld]段添加:
[mysqld] server-id = 100 log_bin = mysql-bin binlog_format = ROW binlog_row_image = FULL expire_logs_days = 30逐个解释为什么这几个参数这么重要:
server-id:在复制链路中,每个节点必须唯一的标识。Dbsyncer作为伪从库去拉binlog时,也需要一个独立server-id,不能和源库本身或者其他从库重复。binlog_format = ROW:只有行级日志才记录了每一行数据变更前后的完整内容。如果是STATEMENT格式,记录的是SQL语句本身,Dbsyncer解析起来困难,而且无法还原字段级变更。binlog_row_image = FULL:确保binlog里包含变更行的所有列的值。如果设置为MINIMAL,只记录需要的列,解析时可能拿不到完整镜像,目标端更新就无从谈起。expire_logs_days:控制binlog保留天数,避免文件无限膨胀占用磁盘。对于持续同步的中间件,建议保留至少3~7天。
修改完重启MySQL:
service mysqld restart重启后确认参数生效:
show variables like 'binlog_format'; show master status;能看到binlog文件名和Position编号就说明一切准备就绪。这一步是整个增量同步的地基。
2.4 授权同步账号
Dbsyncer读取源库binlog需要复制相关的权限,查询数据需要SELECT权限。为安全起见,不建议用root账号,可以单独建一个用户:
CREATE USER 'dbsyncer'@'%' IDENTIFIED BY 'your_password'; GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'dbsyncer'@'%'; FLUSH PRIVILEGES;REPLICATION SLAVE:允许这个账号模拟从库进程请求binlog。REPLICATION CLIENT:允许查看master状态、binlog文件列表等元数据。SELECT:全量同步时需要读源表数据,这个权限必不可少。
目标库的账号则需要具备INSERT、UPDATE、DELETE以及DDL权限,用来执行同步过来的变更。同样建议建专用账号,需要建表就额外给CREATE, ALTER, INDEX, DROP。
3. MySQL到MySQL全量与增量配置全流程
3.1 控制台界面速览
登录Dbsyncer控制台后,左侧是菜单树,核心是“数据源管理”“同步器管理”“任务管理”“系统管理”这几块。
第一次进去先别急着建任务,先把数据源和同步器这两个基础概念理清。官网及项目文档里有完整的功能说明,我这里只讲MySQL to MySQL最常用的操作路径:
- 在“数据源管理”里新增两个MySQL连接,一个源、一个目标。
- 在“同步器管理”里创建同步规则,选择源端表、目标端表以及字段映射。
- 在“任务管理”里创建同步任务,绑定同步器,设定执行方式(全量定时或增量监听)。
- 启动任务,在“日志管理”里观察同步日志。
3.2 数据源配置:源端与目标端
在控制台进入“数据源管理”,点新增。选择MySQL类型,需要填写的核心字段如下:
- 连接名称:自己起一个可识别的名字,比如“订单源库-生产”“订单目标库-报表”。
- IP地址和端口:源库和目标库分别填自己环境的地址。
- 数据库名:默认连接的database,后续同步器会基于这个库选择表。
- 用户名和密码:刚创建的专用账号。
- 驱动选项:连接池大小、超时时间、测试SQL等,新手保持默认即可。
填完后点“测试连接”,能通就说明基本没问题。这里有一个我踩过的坑:如果源库和小目标库在公网环境下且开启了SSL,Dbsyncer连接参数可能需要额外配置SSL相关项,否则会报类似“SSL connection error”的错。报错时优先检查驱动版本和连接串参数,图片化的配置在界面上没有太多高级项,需要根据日志提示手动确认。
3.3 全量同步:创建同步器
同步器是Dbsyncer里比较核心的概念。做一个全量同步,要确定“数据从哪里来”“目标写到哪”“字段怎么对”。操作步骤如下:
步骤1:新建同步器
在“同步器管理”点新增,选择“表同步器”类型。界面会让你选择源端数据源和目标端数据源,就是刚才配好的两个连接。
步骤2:选择源表和目标表
源端选择你要同步的具体表,比如orders;目标端选择目标库中接收数据的表,比如ods_orders。这里要注意:如果目标表不存在,你需要先在目标库建好,或者在Dbsyncer提供的DDL功能中执行建表语句(视版本而定,并非所有版本都内置自动建表)。
步骤3:配置字段映射与过滤条件
字段映射是默认自动进行的,同名同类型的字段会匹配上。如果源表和目标表字段名不一致,逐一手工选对应关系。Dbsyncer还支持配置过滤条件,即只同步满足条件的数据。例如只同步最近7天的订单:
order_time >= DATE_SUB(NOW(), INTERVAL 7 DAY)这个过滤条件会拼接到全量SELECT语句中,减少传输量。
步骤4:设置批次大小
全量同步最关键的一个参数是“批次读取大小”,英文一般叫Chunk Size。这个值决定了一次从源表取多少行、再一次性写多少行。取值偏小,同步速度慢;取值偏大,源库和中间件内存压力大。经验值:
| 数据量 | 建议Chunk Size |
|---|---|
| 10万行以下 | 2000~5000 |
| 10万~500万 | 5000~10000 |
| 500万以上 | 10000~20000 |
实际上管道内的RAM是主要瓶颈,建议小规模先跑个几千试试,观察日志中的同步速度再做调整。
3.4 全量同步:创建并启动任务
同步器配置好以后,进入“任务管理”,新建任务,关联刚创建的同步器。执行类型选择“定时任务”或“立即执行”。
如果是线上首次同步,先跑一次全量,把数据基线建起来。点启动后,任务队列会开始处理,在“日志管理”里能看到同步的实时状态,包括已读取行数、已写入行数、累计耗时。
我在一个700万行的订单表上跑过一次全量,Chunk Size设成10000,耗时大约38秒,速度比较可观。主要瓶颈是MySQL的SELECT和INSERT往返,中间件的处理反而很快。
全量任务结束以后,重点做数据校验。简单的方式就是在源库和目标库分别执行:
select count(*) from orders; select count(*) from ods_orders;数量对得上,再抽样看几条关键字段内容。如果数量不一致,优先检查同步日志里是否跳过了一些脏数据,比如目标表字段长度限制导致插入失败。
3.5 增量同步:配置 binlog 监听
全量同步只是把“当前时刻”的数据复制过去,真正让数据保持连续同步的,是增量同步。增量同步对同步器的要求不同,它不依赖表同步器里的SELECT逻辑,而是依赖binlog解析。
操作路径如下:
在“同步器管理”中新建一个增量监听相关的同步器(不同版本界面名称略有差异,有的叫“日志同步器”),选择目标数据源以及你要消费的binlog位点。如果之前已经跑过全量,那么增量的起点应该从“全量同步完成的那个时刻”开始,这样不会丢数据也不会重复。
然后在“任务管理”创建增量任务,绑定这个同步器,启动。Dbsyncer连接源库的MySQL后,会开始接收binlog事件,识别出orders表上的INSERT、UPDATE、DELETE操作,并转换为目标库的SQL执行。
为了验证增量是否生效,我在源库执行了一条简单UPDATE:
update orders set status = 'PAID' where id = 1001;过了几秒钟,目标库的同一条记录也随之变化了。再执行INSERT和DELETE,同样能看到目标库同步更新。日志中会显示类似“处理binlog 位置 xxx, 事件类型 UPDATE”的信息。
3.6 全量+增量如何组合
实际生产环境,最稳妥的组合是:先做一次全量,等全量任务跑完,立刻启动增量任务,并且把增量任务的起点设置成全量任务结束时的binlog位点。
Dbsyncer在内部其实维护了一个发布订阅机制,增量任务的启动位置可以通过日志界面的binlog位点信息来确认。做法是:
- 全量任务执行前,记录源库当前的binlog文件名和Position:
show master status;全量任务跑完后,记录此刻的binlog文件名和Position。
创建增量任务时,将开始位点设置成第2步记录的值。
这样就能做到全量同步期间产生的数据变更不遗漏。如果Dbsyncer的增量任务支持自动从“当前暂停位置”续跑,那么更省事——先把增量任务停了,做全量,全量完成后再启动增量任务,它会自动从停掉时的位点继续消费。
注意:全量同步过程中,源表数据一直在变化。如果全量跑了很长时间,增量任务没启动的情况下,这期间的新增数据可能被全量的快照覆盖或漏掉。最安全的方式就是在业务低峰期操作,并确保全量结束时间和增量启动时间之差越小越好。
4. 常见问题排查、参数调优与实操心得
4.1 我遇到过的几个典型问题
问题一:测试连接一直失败,报“Access denied for user”
这个大概率是权限没给全,或者账号只允许了特定host登录。检查授权语句是否为'dbsyncer'@'%',以及MySQL是否刷新了权限。还有一种情况是密码中有特殊字符,在连接串里没有正确编码。我后来干脆把密码改成纯字母数字组合,省心不少。
问题二:增量任务日志提示“binlog not found”
有两种可能:一是binlog文件已被清理,比如源库设置了expire_logs_days,而你增量任务停止的时间超过了保留天数;二是binlog位点不连续,Dbsyncer找不到指定文件。解决办法是:把增量任务起点重新设为MySQL当前最新位点。缺点是这样会丢失暂停期间的数据变更,所以线上环境如果暂停增量超过保留期限,就必须通过重跑全量来补偿数据。
问题三:同步到目标端的UPDATE不生效
我遇到过目标表有主键但源表同步过来时主键映射没有配置的情况。如果MySQL binlog格式是ROW且row_image是全量,那INSERT一般没问题,但UPDATE没有主键定位时会走全表更新或者被过滤。解决办法是检查同步器的字段映射,确保目标表的唯一键/主键字段和源表对应。尤其是在跨库同步时,主键字段名如果两边不一致,必须在映射里显式配置。
问题四:同步任务出现OOM或内存飙升
Dbsyncer本身是Java进程,JVM堆内存设置不当或者Chunk Size太大,会造成频繁Full GC甚至OutOfMemoryError。在启动脚本里可以调整JVM参数,比如把堆内存调大到1G或2G:
JAVA_OPTS="-Xms512m -Xmx2048m"同时缩小全量同步的批次大小。增量同步的数据流是持续性的,内存当中需要维护一定数量的缓冲区,如果目标库写入速度跟不上,缓冲区会积压,所以还得看目标库是否有慢SQL或锁竞争。
4.2 常见问题速查表
| 现象 | 可能原因 | 解决方向 |
|---|---|---|
| 连接源库失败 | 账号权限不足、网络不通、驱动不匹配 | 检查授权和网络,确认驱动版本 |
| 全量同步速度慢 | Chunk Size偏小、源库磁盘IO压力大 | 调大Chunk,业务低峰期执行 |
| 增量任务不消费数据 | binlog未开启、位点有误、server-id冲突 | 检查log_bin配置,核对位点,改server-id |
| 目标端数据缺失 | 字段映射不全、过滤条件过严、脏数据报错跳过 | 查看错误日志,完善映射,放宽过滤 |
| 内存溢出 | JVM堆过小、Chunk过大 | 调整JVM参数,降低批次大小 |
| 同步延迟持续增大 | 目标库写入慢、大事务产生大量binlog | 排查目标库锁和SQL性能,考虑拆表同步 |
4.3 关于参数调优的几个经验
全量同步最值得调的参数就是Chunk Size和JDBC连接的超时时间。Chunk Size不是越大越快,过大的时候,MySQL驱动会把所有结果缓存在内存中再交给中间件,反而增加GC压力。比较合理的方式是:先跑一小段数据量观察耗时,再动态调整。
增量同步的核心参数是“批量应用大小”或者说“异步提交间隔”。Dbsyncer可以从binlog里一次解析出很多变更事件,然后批量执行到目标端。如果目标端是MySQL,批量能显著提升吞吐量。比如每秒大量UPDATE短事务的情况下,逐条执行和批量执行的能力差距可能在一倍以上。我调大后,同步延迟从几十秒降到几秒。
另一个容易被忽略的点是目标库表结构。如果目标库的表没有主键,那么UPDATE和DELETE同步时定位记录的成本会很高,因为MySQL需要逐行扫描匹配。建议目标表保留和源表一样的主键,或者至少建一个唯一索引。
4.4 数据一致性校验方法
同步链路搭好了,如何证明数据没问题?除了简单的count比对,还可以做更细致的校验:
抽样校验:在源表和目标表中各取主键相同的若干行,对比关键业务字段是否一致。可以写个简单的SQL脚本对比MD5。
增量时间戳校验:在源表中增加一个
update_time字段,每次变更自动更新;目标表在相同条件下也记录同步到达时间。通过对比源表最新更新时间与目标表同步时间,判断延迟是否在可接受范围。反向核查:在目标库随机选几条记录,去源库对比。这种方法对DELETE场景尤其有效,因为目标库多出来的数据就是同步异常的重要线索。
我自己常写一个简单的校验脚本,逻辑是:从源表按主键分页拉取一批数据的MD5,再在目标表按同样主键拉取对应数据,比对两组MD5是否一致。具体脚本不算复杂,但很实用。建议把这个脚本保留下来,每次同步配置变更后都跑一次。
4.5 关于增量任务长期运行的维护心得
增量任务一旦配置好,它会像守护进程一样7x24小时运行,此时最怕的是源库binlog文件清理策略配置不合理。前面已经说过,expire_logs_days如果设得太短,中间件故障恢复后它会找不到历史binlog,只能重做全量。这里强烈建议把binlog保留时间调长一点,比如7天以上,并配合监控告警,及时发现同步中断。
另外,Dbsyncer会把自己记录的消费位点持久化下来,正常情况下重启中间件,任务会自动从上次的位点继续同步。但如果你在维护过程中手动修正过MySQL的binlog位点(比如做过从库重建),两个位点之间可能就衔接不上,这时最好是手动重置增量任务起点,或重新跑一遍全量。
根据我个人经验,在一个稳定运行的同步系统里,全量与增量相结合能覆盖大多数实际需求——全量负责打底,增量负责兜底。Dbsyncer这个中间件的价值在配置化和日志可视化上体现得最明显,遇到数据问题能快速回放日志定位,这一点比写一堆Python脚本手工维护要省心得多。如果你后续需要对接Elasticsearch或者Kafka,可以在现有基础上继续扩展同步器就能实现,方向是相通的。