☰
Dbsyncer实战:MySQL实时数据同步的全量加增量配置指南
2026/10/9 6:26:01 网站建设 项目流程

做数据同步这个需求,我是被线上库逼出来的。业务库跑了大半年,每天几百万增量,报表想直接查源库,结果慢查询把主库拖得够呛。与其硬扛,不如把数据实时同步到另一个MySQL实例,查询走同步库。听起来简单,真动手就发现全是细节:全量导一次好说,增量怎么持续?进程挂了从哪续?

我最后用的是Dbsyncer这个开源数据同步中间件,管理界面把全量配置和增量配置都图形化了,MySQL到MySQL是它最典型的用法。这篇把部署、binlog准备、全量同步、增量同步以及踩过的坑完整记录下来,照着做基本能跑通。如果你需要快速搭一条MySQL之间的同步链路,又不想自己从零写binlog消费代码,这篇就是给这种情况准备的。

1. 先说清楚:Dbsyncer是什么,为什么拿它做MySQL数据同步

1.1 这个中间件的核心能力与典型使用场景

Dbsyncer是一个开源的、插件化的数据同步中间件,基于Java开发,自带Web管理界面。它的核心能力是“把一张表的数据持续搬到另一个地方”,支持全量同步、增量同步,以及先全量后增量的组合模式。数据源方面覆盖了MySQL、Oracle、SQL Server、PostgreSQL这类主流关系型数据库,非关系型数据库也有支持,插件化设计让新增数据源类型不用改主程序。

实际使用中,典型的场景有这么几种:

  • 数据备份与容灾:每天把核心业务表同步到另一个实例,避免直接在主库上做导出,影响线上性能。
  • 分析库与报表库:线上库数据实时同步到只读分析库,报表查询和业务查询彻底隔离。
  • 异构数据库迁移:比如Oracle存量加增量迁到MySQL,全量先打底、增量追数据,减少停机窗口。
  • 数据归档:按条件过滤同步,只搬运符合条件的行,例如只同步最近N天数据。

标题里只做了MySQL到MySQL,但掌握这套配置逻辑后,换数据源只是换驱动和URL的事,核心同步流程是一样的。

1.2 对比手工脚本和DataX,我为什么选它

决定用Dbsyncer之前,我先把常见的几个方案过了一遍,各有各的适用面,不存在谁全面碾压谁。

方案全量能力增量能力断点与运维成本适合场景
手工脚本(mysqldump加crontab,再自己消费binlog)强,但要自己写优化逻辑弱,自己维护binlog位点高,代码和监控都得自己弄一次性迁移
DataX很强,批量同步效率高支持where条件增量,但实时性一般中,任务调度要另配离线批量迁移、数仓采集
Dbsyncer图形化配置,批量读取基于binlog,实时性高低,界面直接看任务状态和日志实时同步、持续同步

我选Dbsyncer的理由其实就三条。第一,增量实时性足够。它走的是binlog解析路线,业务一提交,目标端就跟着变,不用像DataX那样靠定时任务反复跑where条件。第二,位点和状态管理是现成的。手工脚本最大的痛点是断点,进程一挂还得自己记binlog位置,Dbsyncer会自动落盘记录,重启后接着跑。第三,轻量。一个压缩包解压就能起服务,不需要部署一堆组件,个人开发和中小团队用起来压力小很多。

这里也说句公道话:如果只是离线一次性把几亿行数据搬过去,DataX依然更稳;如果做持续、实时的MySQL数据同步,Dbsyncer性价比很高。

2. 准备工作:Dbsyncer部署和MySQL源端binlog配置一个都不能少

2.1 从下载到访问管理端:Dbsyncer拉起过程

Dbsyncer的部署简单到可以概括成三步:有JDK、解压、启动。

环境上建议JDK 1.8以上,我用的是JDK 8,跑得很稳。下载直接在Gitee搜dbsyncer,进Releases页面拿最新版压缩包,解压后目录结构大概是bin、lib、conf这几个。Linux上执行bin/startup.sh,Windows上执行bin/startup.bat,启动日志会打出一大段信息,最后一行会提示访问地址。我这边默认是http://localhost:8080/dbsyncer,如果端口被占用或改了配置,就以实际日志为准。

浏览器打开后进入登录页,首次使用按页面提示初始化管理员账号密码,后面所有操作都在这个管理端里完成,包括驱动管理、数据源配置、同步策略配置和任务监控。Dbsyncer把同步相关的概念都拆成了独立模块,第一次进去可能觉得菜单有点多,实际上按下面顺序走一遍就顺了。

2.2 源端MySQL必须开的binlog开关和同步账号授权

如果只做全量同步,源端MySQL不开binlog也能跑。但只要涉及增量同步,binlog就是绕不开的前提。Dbsyncer的增量本质是读取源库binlog,所以源库必须满足下面几点。

在my.cnf(Linux)或my.ini(Windows)的[mysqld]段加上:

[mysqld] server_id = 101 log_bin = mysql-bin binlog_format = ROW binlog_row_image = FULL binlog_expire_logs_seconds = 604800 max_binlog_size = 256M

这几个参数的意思顺便解释一下:

  • server_id:不能和集群里其他实例重复,Dbsyncer伪装从库时也依赖这个标识。
  • binlog_format=ROW:增量同步能正常工作的前提。ROW格式记录的是每行数据变更前后的完整内容,STATEMENT格式只记录原始SQL,很多动态SQL根本无法可靠重放。
  • binlog_row_image=FULL:保证UPDATE和DELETE事件里包含所有列的完整镜像,同步端才能可靠映射字段。
  • binlog_expire_logs_seconds:binlog保留时间,建议至少7天,防止任务停太久导致位点失效。
  • max_binlog_size:单个binlog文件大小,到了就滚动切换,256M是比较常见的值。

然后建一个专用同步账号并授权:

CREATE USER 'dbsyncer'@'%' IDENTIFIED BY 'Dbsyncer@123'; GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'dbsyncer'@'%'; FLUSH PRIVILEGES;

SELECT是给全量同步查数据用的;REPLICATION SLAVE是Dbsyncer伪装从库拉取binlog的关键权限;REPLICATION CLIENT用来读取master status,定位当前binlog文件名和位置。如果目标端也要Dbsyncer连过去写数据,目标库的账号给到SELECT、INSERT、UPDATE、DELETE权限即可。

注意:如果源端是MySQL 8.x,默认认证插件是caching_sha2_password,Dbsyncer的驱动版本必须配套,否则连接直接失败,具体处理方式见后面踩坑部分。

2.3 动手验证binlog是否真正生效

配置完my.cnf别急着去Dbsyncer建任务,先确认binlog到底开没开。MySQL重启后执行下面几条命令:

SHOW VARIABLES LIKE 'log_bin%'; SHOW VARIABLES LIKE 'binlog_format'; SHOW MASTER STATUS;

正常会看到log_bin=ON,binlog_format=ROW,以及一个类似mysql-bin.000001的文件名和当前位点。很多人部署完忘了重启MySQL,或者配置文件路径写错,这步能快速排除。

验证完源端binlog后,准备工作就齐了。下一步进入管理端,开始配全量同步。

3. 全量同步实操:装驱动、配数据源、建任务三步跑通

3.1 驱动管理:为什么还要手动装JDBC驱动

首次打开Dbsyncer管理端,最先要做的不是建任务,而是先到驱动管理里把MySQL的JDBC驱动装好。Dbsyncer的设计原则是不内置数据库驱动,驱动文件由使用者自己上传。第一次用可能觉得多此一举,实际用过就知道这是对的:数据库版本升级、驱动版本冲突这类问题不会再赖到工具头上,你可以完全控制自己环境里的驱动版本。

操作上很简单:驱动管理里新增一条记录,驱动名称随便起一个方便识别的,比如mysql8-driver,驱动类填com.mysql.cj.jdbc.Driver(MySQL 5.x驱动则填com.mysql.jdbc.Driver),然后把mysql-connector-j的jar包上传上去。

版本选择有个坑:MySQL 5.7的实例用mysql-connector-j 5.1.x没问题,但MySQL 8.0以上的实例必须要用8.x驱动,否则认证方式不匹配,测试连接会直接报错。这点的具体表现放到第五部分细说。

3.2 数据源配置:源端和目标端的连接参数

驱动装好后,进入数据源管理,分别新增源端、目标端两个数据源。Dbsyncer里的数据源是逻辑概念,一个数据源对应一个数据库连接,后面建同步任务时都从已配置的数据源里选。

我在源端填的是这么一串URL:

jdbc:mysql://127.0.0.1:3306/source_db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true

目标端URL除了库名换成target_db,其余一样。几个参数不是随手加的:

  • serverTimezone=Asia/Shanghai:Java连接MySQL 8时如果不指定时区,驱动会拿系统时区和数据库时区比较,容易报The server time zone value这类错误。
  • useSSL=false:本地或内网同步不需要SSL,开着反而可能引入证书问题。
  • allowPublicKeyRetrieval=true:MySQL 8使用caching_sha2_password认证时,客户端要允许公共密钥检索,不配上这个即使驱动版本对了也可能报错。
  • characterEncoding=utf8:防止中文乱码,尤其是源表有varchar存中文的场景。

填完用户名密码后,Dbsyncer提供测试连接功能,两条数据源都通过测试,再往下建任务。

3.3 创建全量同步任务并验证两侧数据一致

数据源就绪后,在同步策略管理里新增同步策略。需要注意,Dbsyncer这里的“同步策略”可以理解为一条带配置的同步规则,创建完还要手动启动,才会变成实际运行的任务。

我新建策略时这样填:

  • 同步策略名称:demo_full
  • 源数据源/目标数据源:选刚才配好的source_db和target_db
  • 同步方式:全量
  • 源表和目标表:先各选一张测试表,比如t_user
  • 字段映射:默认同名映射,也可以只同步部分字段
  • 批量大小:我设了5000,这个参数决定全量过程中每次从源库读多少行、往目标库写多少行

启动任务后,策略状态会从待执行变成执行中,界面上能看到同步进度和日志。全量过程别光盯着状态,直接去两侧库验证。源库和目标库各执行一次COUNT(*),再抽查几条记录,对比主键、更新时间这类关键字段。

我第一次跑的时候源表有320万行,批量大小5000下大概几分钟跑完,速度在可接受范围。全量同步的逻辑是纯JDBC读取加批量写入,不依赖binlog,所以即使源库binlog没有开启,这步也能正常完成。

4. 增量同步实操:binlog解析、位点管理和全量增量衔接

4.1 增量同步到底在原理上做了什么

全量同步跑通后,增量才是真正体现Dbsyncer价值的地方。它的增量同步思路和大多数CDC工具一致:伪装成MySQL的一个从库实例,向主库请求binlog流,拿到binlog数据后解析出每一行变更事件,转换成对应的INSERT、UPDATE、DELETE语句在目标端执行。

这里面有几个关键点:

  • 为什么能实时:binlog本身就是MySQL主从复制的底层日志,Dbsyncer订阅它,相当于和从库同步站在同一条数据流上,业务提交后几乎没有延迟。
  • 为什么必须ROW格式:ROW格式下,binlog记录的是每行变更前后的列值,同步端可以直接按列映射;STATEMENT格式只记录类似的SQL片段,遇到NOW()、LIMIT这类动态语义没法可靠重放。
  • 为什么建议源表有主键:增量解析出来的UPDATE、DELETE事件,最终要在目标端精确命中行,主键是最高效的定位依据。没有主键的表虽然也能凑合,但性能和准确率都会下降。

理解了原理,配置时就不会稀里糊涂。增量同步不是因为界面选了一下就生效,而是源端binlog、权限、驱动、表主键这些条件共同起作用。

4.2 “先全量后增量”的衔接方式和位点说明

这里给一个强烈建议:不要单独配置一个纯增量任务作为同步的第一条任务。原因很简单,增量任务只能从某个时间点开始追binlog,它管不了这个时间点之前的历史数据。如果只配增量,目标端表里没有数据,增量也就失去了意义。

Dbsyncer里稳妥的玩法是同步方式直接选“全量+增量”,让任务自己衔接:启动后先把当前表数据全量拉一遍,全量完成自动进入增量监听。这套组合非常适合从零搭建一条实时同步链路的场景,也就是标题里说的这个用法。

如果已经有了一个全量表基线,只想补增量,可以在增量策略里指定起始位点,也就是binlog文件名和position,或者让Dbsyncer从源库当前时刻开始记录位点。位置从哪来?源库执行SHOW MASTER STATUS就能看到当前Binlog_File和Position,把它作为起点,任务就从这里往后追。

建议:首次搭建同步链路,统一采用“全量+增量”模式。全量负责把历史数据打底,增量负责追实时变化,衔接过程由工具处理,不需要自己反复切模式。

4.3 任务重启后为什么能断点续传

增量任务最值钱的能力是断点续传。Dbsyncer在消费binlog时,会把已经消费到的位点持久化到本地存储,任务运行中也好,进程异常退出也好,重启后它都会从记录位点继续拉取,目标端不会重复写入,也不会丢掉中间变更。

这对运维来说省掉了很多麻烦。手工脚本时代,我最怕凌晨同步进程挂掉,第二天发现binlog消费位点记在内存里、进程重启就被清零,然后要么重新全量,要么手动把缺失时间段补上。Dbsyncer把位点管理和任务重启接上了,这也是它适合长期运行的关键。

不过断点续传有个前提需要记住:源端binlog配置的保留时间要大于任务可能停机的时间。比如binlog_expire_logs_seconds设了7天,任务停机一两天都没问题,但如果停机超过7天,源端binlog被清理,位点找不到对应事件,就只能重新做一次全量基线了。

5. 踩坑记录:认证插件、表结构差异与增量丢失的排查链路

5.1 驱动连不上MySQL 8:认证插件不一致

第一次配数据源,测试连接就给我上了一课。环境是MySQL 8.0,我图省事直接用了之前的mysql-connector-j 5.1.47,结果报错Public Key Retrieval is not allowed,有的版本还报Access denied for user。

根因很明确:MySQL 8默认的认证插件是caching_sha2_password,5.x驱动不认识这个插件,握手阶段直接失败。

解决办法有两条路,我建议走第一条:

  • 升级驱动到mysql-connector-j 8.0.x,驱动类用com.mysql.cj.jdbc.Driver,URL里带上allowPublicKeyRetrieval=true&useSSL=false。
  • 如果短时间内不想换驱动,可以把同步账号的认证插件改回mysql_native_password,比如执行ALTER USER 'dbsyncer'@'%' IDENTIFIED WITH mysql_native_password BY 'Dbsyncer@123';。但这只是临时绕法,MySQL后续版本会逐步移除旧插件,长期还是要升级驱动。

这个坑的排查链路很短,但很有代表性:报错信息往往直接指向认证方式,不用怀疑URL写错,先看一眼驱动版本和MySQL版本是否匹配。

5.2 目标表结构不一致导致全量同步中断

第二个坑是建完全量任务后,任务启动没几分钟就从执行中变成失败状态,日志里飘着字段长度不够、Data truncation这类错误。

我的排查流程是这样的:

  1. 先在管理端打开同步日志,找到具体报错SQL,定位到是哪个字段的问题。
  2. 拿源表执行SHOW CREATE TABLE,和目标表的SHOW CREATE TABLE对比,发现目标表的两个varchar字段长度比源表短,数据一超长就被截断报错。
  3. 调整目标表字段结构,和源表对齐后,重启任务重新全量,再跑就通了。

这类问题其实可以在建任务之前就避免。全量同步启动之前,先跑一遍两边的SHOW CREATE TABLE做差异对比,重点看字段长度、类型、字符集和是否允许NULL。字符集不一致还会引发中文乱码或者索引长度超限,比字段长度问题更隐蔽。另外,如果目标表已经有部分数据,最好先清空,避免主键冲突导致任务中断,这是我后来在另一张表上再次踩到的教训。

5.3 增量任务显示运行但目标端就是没新数据

第三个坑最典型,现象是任务状态明明显示运行中,但我在源端INSERT了几条测试数据,目标端一点动静都没有。这个问题我拆了好几步才定位:

  1. 先确认不是假运行。在管理端刷新任务状态,看最近同步时间是不是一直在跳。如果在跳但目标端没数据,多半是映射或目标端写库的问题;如果同步时间根本不跳,说明binlog消费卡住了或者压根没消费。
  2. 去源库看binlog有没有真正记录变更。执行SHOW MASTER STATUS,记录Binlog_File和Position,然后手动UPDATE一条数据,再查一次Position,如果没变,说明数据根本没写进binlog,那就回头检查源库binlog开关。
  3. 如果Position变了,再执行SHOW BINLOG EVENTS IN 'mysql-bin.000001',确认这张表的变更事件确实以ROW格式存在。
  4. 最后查Dbsyncer日志。我这边根因是同步账号在目标库权限不够,INSERT被拒,但任务没有立刻标记失败,一直显示运行中,看起来就像数据没过来。把目标库账号权限补上,再触发一次变更,数据就正常同步了。

排查这类问题的核心思路是分层:先看任务层状态,再看binlog层数据,最后看权限和映射层。从外到里一步步缩小范围,比盲改配置高效得多。

5.4 顺手调过的三个性能参数

除了排错,顺手聊一下我调过的三个性能相关参数:

  • 批量大小:全量同步的批量大小设太小,比如几百,同步会慢得让人着急;设太大,比如一次几万,源库压力会明显上升。我一般从5000起调,先观察两侧实例的负载再定。
  • 目标端索引:目标表索引太多时,批量INSERT会被索引维护拖慢。如果同步的是明细数据大表,可以在全量期间临时禁掉非唯一索引,全量结束再建回来。
  • 增量单线程:增量事件在部分版本里按事务顺序串行消费,这和binlog本身的顺序性有关。想提高增量处理吞吐,先确认表主键设计合理,再考虑把单表拆成多任务并行。

这些参数没有绝对最优值,最后还是要看具体实例规格和表结构。

把Dbsyncer这条链路完整跑下来之后,我对同步中间件的理解又深了一层。同步这件事真正难的不是把数据搬过去,而是位点管理、异常恢复和映射关系这些模块能不能长时间稳定运行。Dbsyncer把这些都做进了界面里,用它搭MySQL到MySQL的全量增量同步确实很省心。后面再遇到新的同步需求,我大概率会先在这套框架里试一遍再谈定制。如果你也准备上手,我的建议是先找一张小表,按全量加增量走一遍,把binlog配置、驱动版本、表结构差异这些变量都验证到位,再去碰大表和生产环境,心里就有底了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询