作者:任仲禹 爱可生DBA团队成员,擅长故障分析和性能优化,文章相关技术问题,欢迎大家一起讨论。 本文来源:原创投稿 爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。背景 源于某客户的需求,存在线上某业务MySQL库因为数据量及业务读写压力较大,需要将业务数据迁移到DBLE分布式数据库,但同时因为业务为7x24h,能够停机的时间窗口较短,所以需要考虑数据实时同步的方案。 过往DBLE的业务上线基本为全新部署,数据实时同步的情况极少实施,去年DTLE发布后这一问题得到了些改善,今天我们来实践下。环境准备1。目标端DBLE集群部署安装DBLE软件、后端分片MySQL库过程略DBLE版本3。20。10。8、MySQL版本5。7。25sharding。xmllt;?xmlversion1。0?!DOCTYPEdble:shardingSYSTEMsharding。dtddble:shardingxmlns:dblehttp:dble。cloudversion4。0schemanamedtlesqlMaxLimit1shardingNodedn01singleTablenamegtidexecutedv4shardingNodedn01sqlMaxLimit1singleTableschemaschemanamerensqlMaxLimit1shardingNodedn01shardingTablenametestshardingNodedn01,dn02,dn03,dn04sqlMaxLimit1shardingColumnidfunctionfuncjumphashshardingTableschemashardingNodenamedn03dbGroupdhmysqlcluster02databasedhdn03shardingNodeshardingNodenamedn04dbGroupdhmysqlcluster02databasedhdn04shardingNodeshardingNodenamedn02dbGroupdhmysqlcluster01databasedhdn02shardingNodeshardingNodenamedn01dbGroupdhmysqlcluster01databasedhdn01shardingNodefunctionnamefuncjumphashclassjumpStringHashpropertynamepartitionCount4propertypropertynamehashSlice0:1propertyfunctiondble:shardingdb。xmllt;?xmlversion1。0?!DOCTYPEdble:dbSYSTEMdb。dtddble:dbxmlns:dblehttp:dble。cloudversion4。0dbGroupnamedhmysqlcluster02rwSplitMode0delayThreshold1heartbeattimeout0errorRetryCount0showslavestatusheartbeatdbInstancename10。186。61。133326dh1url10。186。61。13:3326userdbleuserpasswordjpfmxIeMt1vxAJ6zd6Q10PGRRiQj023DlYXuOr3C4VXTdV5GJaOIv5iVmWCwpXcucnzi02HVlT7ADXm6QmaxCon100minCon10primarytruereadWeight0idmysqli63009usingDecrypttruedbInstancedbGroupdbGroupnamedhmysqlcluster01rwSplitMode0delayThreshold1heartbeattimeout0errorRetryCount0showslavestatusheartbeatdbInstancename10。186。61。113316dh1url10。186。61。11:3316userdbleuserpasswordQQWRF80AGNbx4jIAxb2Ww7Myol1ntlyzGmA1A3PXVISmRDi5pgRnLLwYsXoLmH0jiv1qZAkqIBHv6YgXAgmaxCon100minCon10primarytruereadWeight0idmysql47vn84usingDecrypttruedbInstancedbGroupdble:dbuser。xmllt;?xmlversion1。0?!DOCTYPEdble:userSYSTEMuser。dtddble:userxmlns:dblehttp:dble。cloudversion4。0managerUsernamerootpasswordCrjpLhvVJkHk0EPW35Y07dUeTimf52zMqClYQkIAN3dqiG1DVUe9Zr4JLh8Kl1KH1zd7YTKu5w04QgdyQeDwusingDecrypttruemanagerUsershardingUsernamerenschemasren,dtlepasswordPC2KazQiS3ZZ6uojBJ91MZIqYqGczspQebyBZOC9xKAAkAFrqEDC9OPnvObAyO4P8Zu3vHQJrljM040KdgusingDecrypttruereadOnlyfalsemaxCon0blacklistdefaultblacklistshardingUserdble:user2。源端和目标端测试表创建源端MySQL数据库软件安装略源端MySQL与目标端DBLE都需要创建测试表名:testuseren;CREATETABLEtest(idint(11)NOTNULLAUTOINCREMENT,namevarchar(20)COLLATEutf8mb4binDEFAULTNULL,cityvarchar(20)COLLATEutf8mb4binDEFAULTNULL,dtdatetimeDEFAULTCURRENTTIMESTAMP,PRIMARYKEY(id),KEYidxctiy(city))ENGINEInnoDB;3。部署单节点DTLEDTLE社区版本GitHub下载地址:https:github。comactiontechdtle下载完成后直接rpm安装(本示例使用内部QA验证版本)rpmivhprefixdatadtledtleee9。9。9。9。x8664。rpm安装完成确认启动正常curlXGET127。0。0。1:4646v1nodessjq〔{Address:127。0。0。1,ID:223c31b405cda763b3e7dbea6d416576,Datacenter:dc1,Name:nomad0,NodeClass:,Version:1。1。2,Drain:false,SchedulingEligibility:eligible,Status:ready,StatusDescription:,Drivers:{dtle:{Attributes:{driver。dtle。fullversion:9。9。9。9mastera65ee13,driver。dtle:true,driver。dtle。version:9。9。9。9},Detected:true,Healthy:true,HealthDescription:Healthy,UpdateTime:20220228T07:45:15。650289984Z〕创建MySQLToDBLE任务一、全量同步1。准备job文件catjob。json{Job:{ID:mysqlToDBLE,Datacenters:〔dc1〕,TaskGroups:〔{Name:src,Tasks:〔{Name:src,Driver:dtle,Config:{Gtid:,ReplicateDoDb:〔{TableSchema:ren,Tables:〔{TableName:test}〕}〕,ConnectionConfig:{Host:10。186。61。11,Port:3306,User:root,Password:root}}}〕},{Name:dest,Tasks:〔{Name:dest,Driver:dtle,Config:{ConnectionConfig:{Host:10。186。61。10,Port:8066,User:ren,Password:ren}}}〕}〕}}2。准备全量复制数据源端MySQL库执行mysqlinsertintotestvalues(1,ren,sh,now());mysqlinsertintotestvalues(2,jack,bj,now());mysqlinsertintotestvalues(3,tom,sz,now());3。启动同步任务curlXPOSThttp:127。0。0。1:4646v1jobsdjob。jsonsjq{EvalID:88ab4a4298b7696e0f9808c1fe3ee4bd,EvalCreateIndex:12310,JobModifyIndex:12310,Warnings:,Index:12310,LastContact:0,KnownLeader:false}4。检查同步情况确认全量数据同步完成目标端DBLE中执行mysqluseren;Databasechangedmysqlshowtables;Tablesinrentestgtidexecutedv42rowsinset(0。01sec)mysqlselectfromtest;idnamecitydt1rensh2022030706:53:302jackbj2022030706:53:413tomsz2022030706:53:593rowsinset(0。01sec)源端MySQL写入增量测试数据mysqlinsertintotestselectnull,mike,nj,now();QueryOK,1rowaffected(0。01sec)Records:1Duplicates:0Warnings:0mysqlinsertintotestselectnull,mike4,nj,now();QueryOK,1rowaffected(0。01sec)Records:1Duplicates:0Warnings:0mysqlupdatetestsetcityshwherenamelikemike;QueryOK,4rowsaffected(0。01sec)Rowsmatched:4Changed:4Warnings:0mysqlselectfromtest;idnamecitydt1rensh2022030706:53:302jackbj2022030706:53:413tomsz2022030706:53:5945mikesh2022030708:03:5746mike2sh2022030708:04:0247mike3sh2022030708:04:0548mike4sh2022030708:04:097rowsinset(0。01sec)目标端DBLE检查增量同步情况mysqlselectfromtest;idnamecitydt1rensh2022030706:53:302jackbj2022030706:53:413tomsz2022030706:53:5945mikesh2022030708:03:5746mike2sh2022030708:04:0247mike3sh2022030708:04:0548mike4sh2022030708:04:097rowsinset(0。04sec)mysqlexplainselectfromtestwhereid1;SHARDINGNODETYPESQLREFdn01BASESQLselectfromtestwhereid11rowinset(0。03sec)二、基于GTID位点增量同步1。销毁全量同步任务cddatadtleusrbinlltotal188836rwxrxrx1rootroot107811060Mar172020consulrwxrxrx1rootroot85550512Jun222021nomad。nomadjobstatusIDTypePriorityStatusSubmitDatemysqlToDBLEservice50running20220307T15:47:3108:00mysqltoMysqlsyncservice50running20220303T16:06:1008:00。nomadjobstoppurgemysqlToDBLEDeployment433ed3d4successful。nomadjobstatusIDTypePriorityStatusSubmitDatemysqltoMysqlsyncservice50running20220303T16:06:1008:002。记录源端GTID位点记录源端MySQL需要开始的GTID位点mysqlshowmasterstatusG1。rowFile:mysqlbin。000178ExecutedGtidSet:442dbe9200c311eca0cf02000aba3d0b:149705119,cdc6fb6200c211eca25902000aba3d0a:135551rowinset(0。01sec)插入增量数据(模拟业务新增数据)mysqlinsertintotestselect88,sync01,wh,now();mysqlinsertintotestselect99,sync02,wh,now();源端MySQL确认数据已插入mysqlselectfromtest;idnamecitydt1rensh2022030706:53:3048mike4sh2022030708:04:0988sync01wh2022030708:24:2099sync02wh2022030708:24:319rowsinset(0。00sec)目标端DBLE数据因同步job已销毁,新插入数据未同步过来mysqlselectfromtest;idnamecitydt1rensh2022030706:53:3048mike4sh2022030708:04:097rowsinset(0。00sec)3。准备增量同步job文件catjob。json{Job:{ID:mysqlToDBLE,Datacenters:〔dc1〕,TaskGroups:〔{Name:src,Tasks:〔{Name:src,Driver:dtle,Config:{Gtid:442dbe9200c311eca0cf02000aba3d0b:149705119,cdc6fb6200c211eca25902000aba3d0a:13555,ReplicateDoDb:〔{TableSchema:ren,Tables:〔{TableName:test}〕}〕,ConnectionConfig:{Host:10。186。61。11,Port:3306,User:root,Password:root}}}〕},{Name:dest,Tasks:〔{Name:dest,Driver:dtle,Config:{ConnectionConfig:{Host:10。186。61。10,Port:8066,User:ren,Password:ren}}}〕}〕}}4。开始增量同步任务curlXPOSThttp:127。0。0。1:4646v1jobsdjob。jsonsjq{EvalID:cad6fb1962d367aa6f5cfbb79f8016d2,EvalCreateIndex:12855,JobModifyIndex:12855,Warnings:,Index:12855,LastContact:0,KnownLeader:false}5。检查同步情况目标端DBLE中查看到GTID位点之后的数据已同步过来mysqlselectfromtest;idnamecitydt1rensh2022030706:53:3048mike4sh2022030708:04:0988sync01wh2022030708:24:2099sync02wh2022030708:24:3111rowsinset(0。06sec)6。其它DML及DDL同步验证下其它update、delete语句及DDL语句同步情况源端MySQL执行操作mysqldeletefromtestwhereid100;QueryOK,2rowsaffected(0。01sec)mysqldeletefromtestwhereid3;QueryOK,6rowsaffected(0。01sec)mysqlupdatetestsetnameactionskywhereid3;QueryOK,1rowaffected(0。00sec)Rowsmatched:1Changed:1Warnings:0目标端DBLE检查同步情况mysqlselectfromtest;idnamecitydt1rensh2022030706:53:302jackbj2022030706:53:413actionskysz2022030706:53:593rowsinset(0。01sec)源端MySQL执行DDL操作mysqlaltertabletestaddcolumninfovarchar(20)defaulthello;mysqlupdatetestsetinfothankswhereid3;mysqlaltertabletestaddindexidxinfo(info);目标端DBLE可以进行DDL同步(篇幅所限,实际上DBLE兼容的DDL语句都能同步成功)mysqlselectfromtest;idnamecitydtinfo1rensh2022030706:53:30hello2jackbj2022030706:53:41hello3actionskysz2022030706:53:59thanks3rowsinset(0。02sec)mysqlshowcreatetabletestG1。rowTable:testCreateTable:CREATETABLEtest(idint(11)NOTNULLAUTOINCREMENT,namevarchar(20)COLLATEutf8mb4binDEFAULTNULL,cityvarchar(20)COLLATEutf8mb4binDEFAULTNULL,dtdatetimeDEFAULTCURRENTTIMESTAMP,infovarchar(20)COLLATEutf8mb4binDEFAULThello,PRIMARYKEY(id),KEYidxctiy(city),KEYidxinfo(info))ENGINEInnoDBAUTOINCREMENT89DEFAULTCHARSETutf8mb4COLLATEutf8mb4bin1rowinset(0。01sec)配置MySQLToDBLE注意事项1。检测连接失败问题问题描述:DTLE配置JOB过程中,检测连接失败,nomad日志报错ERROR1064(HY000):java。sql。SQLSyntaxErrorException:illegalvalue〔TRUE〕原因:DTLE下发的检测客户端语句setautocommittrue,在DBLE某些版本中不支持解决:升级DBLE到3。20。10。6版本及之后2。任务启动后同步失败报dtle不存在问题描述:DTLE同步任务启动后报错,nomad日志出现Cantcreatedatabasedtlethatdoesn’texists。原因:DTLEToMySQL,不会出现该种报错DTLEToDBLE,由于DBLE中间件中schema的创建方式与普通MySQL不一致,所以该create语法不支持解决:需要对DBLE进行额外的SchemaTable配置,参考前文sharding。xml和user。xml中相关配置3。任务启动后同步失败报Datatoolong问题描述:DTLE同步任务启动后报错,nomad日志出现appliererrorrestart:insertgno:Error1406:Datatoolongforcolumnsourceuuidatrow1原因:DTLE在DBLE中创建的表gtidexecutedv4中,字段sourceuuid的Binary数据类型长度不够也可通过排查DBLE中间件日志(corelogdble。log),报错信息为executesqlerr:errNo:1406Datatoolongforcolumnsourceuuidatrow1解决:DBLE中,修改字段altertablegtidexecutedv4modifycolumnsourceuuidbinary(60);结论DTLE目前功能基本可以满足MySQLDBLE间数据实施同步需求,不过需要注意的是,不建议采用本文所提到的全量同步方式生产环境实施由于MySQL老库数据量较大,可以先将数据全量逻辑备份出来(需记录GTID位点),再通过DBLE自带的split工具进行拆分后进行导入,然后再使用DTLE基于GTID位点增量同步的方式进行数据同步DTLE创建ToDBLE任务前需要关注下前文所示注意事项,尤其是提前准备好sharding。xml、user。xml文件并创建好DTLE的元数据表gtidexecutedv4。