ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

数据库迁移工具实战——把迁移任务变成可追踪流水线

数据库迁移工具实战——把迁移任务变成可追踪流水线 文章目录先给每次采集一个身份再把云、端、服务放进同一张图用样本验证转换别让全量导入成为第一次测试采集不是复制业务数据最后再看协同工具值不值得用给任务分级才能让多人协作不互相等待切换演练要把“回退”当成正常路径让 DBA 支持沉淀为下一次的规则平时我做迁移项目的时候最怕听见别人跟我说“这个库已经扫过了”。这句话听起来好像有进度了。其实呢它里面缺了三个很要命的信息。谁扫的什么时候扫的扫出来的是什么版本还有扫完的结果后来到底拿去转换和验证没有这些问题都没回答。项目稍微一大迁移这些事就会变成一堆碎片。散落在哪呢聊天记录里一点脚本目录里一点个人电脑的表格里再一点。这是一个问题。那为什么会这样呢原因就在于没有一条线把它们串起来。所以这篇聊数据库迁移工具实战的文章我就不按那种“点击开始迁移”的套路写了。咱们从哪写起呢从搞一条能追踪的流水线写起。我拿金仓 KDMS 那个云、端、服务的思路来当个参考。我会把现场采集、云端评估、问题处理还有 DBA 支持全部拆成一条条能对得上的记录。工具干吗的呢工具就是帮你把那些机械的活儿干掉。团队干吗的呢团队负责把这些记录变成能交差的东西。先给每次采集一个身份对于一次采集我个人的习惯是把它当成一次“快照”。也就是说它不是去把上一次的结果给盖掉。为什么要这样搞呢因为只有快照能分得清谁是谁。这样到了后面你才搞得明白某个对象到底是这次新冒出来的还是上次就在那儿但是一直没处理完。下面这个呢是一份我平时用来练习的台账结构。大家注意看它并不是说就代表了 KDMS 里头的内部表。它其实仅仅只是帮我在做项目的时候把字段的口径给统一一下而已。CREATETABLEcollection_snapshot(snapshot_idBIGINTPRIMARYKEY,project_codeVARCHAR(64)NOTNULL,source_nameVARCHAR(128)NOTNULL,collected_atTIMESTAMPNOTNULL,collectorVARCHAR(64)NOTNULL,source_versionVARCHAR(64)NOTNULL,statusVARCHAR(16)NOTNULL,manifest_hashVARCHAR(64)NOTNULL);CREATETABLEcollection_object(snapshot_idBIGINTNOTNULL,object_typeVARCHAR(32)NOTNULL,object_nameVARCHAR(256)NOTNULL,definition_hashVARCHAR(64)NOTNULL,PRIMARYKEY(snapshot_id,object_type,object_name));我会把端上也就是现场采集到的对象清单通通倒进这两张表里。接着呢拿同一个源库的两个快照来做个对比。新出来的对象还有定义发生改变的对象这些是不应该跟以前的老问题混在一块儿的。SELECTCOALESCE(newer.object_type,older.object_type)ASobject_type,COALESCE(newer.object_name,older.object_name)ASobject_name,CASEWHENolder.object_nameISNULLTHENADDEDWHENnewer.object_nameISNULLTHENREMOVEDWHENolder.definition_hashnewer.definition_hashTHENCHANGEDENDASchange_typeFROMcollection_objectASnewerFULLJOINcollection_objectASolderONolder.object_typenewer.object_typeANDolder.object_namenewer.object_nameANDolder.snapshot_id:previous_snapshotWHEREnewer.snapshot_id:current_snapshotAND(older.object_nameISNULLORnewer.object_nameISNULLORolder.definition_hashnewer.definition_hash);这里边用到了FULL JOIN。其实这仅仅是为了把差异分析的思路表达出来。具体到你的目标环境里语法和执行计划怎么搞那得你自己去验证。这里的关键根本不在于你能把这条 SQL 写出来。而在于什么呢在于你每次重新采集完之后都能回答出来“到底哪里变了”这个问题。再把云、端、服务放进同一张图以前那种老式的单机版迁移工具它把扫描、转换还有日志全扔在一台机器上。如果是小项目的话那确实挺方便的。但是遇到多个人一起干活的情况这就很麻烦了。你根本搞不清楚到底是谁用了哪一个版本的规则。那么 KDMS 搞的这个“云端服务”呢就比较适合把大家的职责给拉开。端上的人就在现场采集。云端负责把东西汇总起来做评估然后把任务分下去。服务那边呢就交给 DBA 去处理那些高风险的问题。否是端侧连接源库只读采集云端快照与迁移评估任务池自动转换/人工改造端侧样本迁移和验证服务侧DBA复核与答疑证据齐全?批次验收与切换准备在云端的任务池里面我会只留那些能推着项目往前走的字段。比如来源快照、对象名字、问题是什么类型、谁负责处理、什么时候截止还有验证的证据。如果一个问题没有来源快照这就很麻烦。等新一轮采集完它就没有上下文了你不知道它对应哪里的东西。如果一个任务没有验证证据那也不能说脚本生成成功了就直接把它关掉。不行得有证据。CREATETABLEmigration_issue(issue_idBIGINTPRIMARYKEY,snapshot_idBIGINTNOTNULL,object_nameVARCHAR(256)NOTNULL,issue_categoryVARCHAR(64)NOTNULL,resolution_typeVARCHAR(32)NOTNULL,owner_nameVARCHAR(64),statusVARCHAR(16)NOTNULL,verified_atTIMESTAMP,evidence_uriVARCHAR(512));SELECTissue_category,status,COUNT(*)ASissue_countFROMmigration_issueWHEREsnapshot_id:snapshot_idGROUPBYissue_category,statusORDERBYissue_category,status;这么一汇总呢原来那种模糊的“还有多少问题”就变成了很具体的东西。什么类别什么状态一目了然。项目经理拿着这个就可以去排期了。DBA 也可以直接挑那些需要靠人脑去判断语义的对象来看。开发人员呢也就不用再去几十份日志里面扒拉自己的任务了。用样本验证转换别让全量导入成为第一次测试我一般会先挑三种样本出来。哪三种呢对象复杂度特别高的、平时调用特别频繁的还有业务风险非常大的。那种表结构极其简单、数据量又小的对象你不用先管它们。但是核心交易的 SQL 还有报表的 SQL你必须得覆盖到。你要搞清楚样本阶段你的任务是去验证规则。而不是说在这个时候去拼导入的数据总量。下面这段 Python 代码呢是我平时用来生成“对象级回归清单”的一个小骨架。它就是根据转换的状态把任务扔到不同的队列里去。至于说真正的连库啊、执行啊、异常处理啊这些就得看你们项目具体的环境自己去补齐了。fromcollectionsimportdefaultdict queuesdefaultdict(list)foriteminassessment_items:ifitem.statusAUTO_CONVERTED:queues[smoke_test].append(item)elifitem.statusNEEDS_REVIEW:queues[dba_review].append(item)else:queues[application_refactor].append(item)forqueue_name,itemsinqueues.items():print(queue_name,len(items))foriteminitems[:5]:print( ,item.object_name,item.reason)这里我特别在意的是NEEDS_REVIEW这个队列。自动转换搞不定的对象数量上不一定会有很多。但是呢它里面很可能藏着那种很复杂的存储过程或者有什么外部调用再或者就是牵扯到业务语义了。把这些东西尽早地丢给 DBA 和开发让他们一块儿评审。这比你等到切换的那天晚上临时去改脚本要稳当太多了。采集不是复制业务数据在端上做采集有一个原则必须得遵守就是最小权限。我们做迁移评估通常来说先要的只是元数据、依赖关系还有 SQL 的线索。这并不等于说你要把生产库里的业务数据完完整整地给导出来。如果有些表你需要抽样那也得先拉业务的人和安全的人来确认范围。确认完了再把那些敏感的字段做脱敏处理。还有你用什么账号连的、什么时候采的、采了多大范围、结果包的校验值是多少这些全都要记下来。你可以用下面这个查询来查一下看看“采上来的数量看着是不是完整的”。这个查询它当然不能保证你所有对象都绝对正确。但是呢它能帮你尽早发现一种情况那就是某一类型的对象彻底丢了一个都没采上来的情况SELECTobject_type,SUM(source_count)ASsource_count,SUM(collected_count)AScollected_count,SUM(source_count-collected_count)ASgap_countFROMcollection_summaryWHEREsnapshot_id:snapshot_idGROUPBYobject_typeHAVINGSUM(source_count-collected_count)0ORDERBYgap_countDESC;最后再看协同工具值不值得用我去评判一个数据库迁移工具好不好用不是光看它能不能给我生成 DDL 就行的。更要紧的是什么呢是看它能不能把快照留住。能不能把端上的采集连起来。能不能把问题准确分给该管的人。能不能让 DBA 说的那些话回到任务记录里去。还有在跑样本和真正切换的时候能不能把证据留下来。KDMS 搞的这个“云端服务”架构其实就是给了一个闭环的思路。云端呢把整个项目的视图统起来。端侧呢把现场的边界守住。服务那边就是补上那些复杂问题需要人来判断的短板。工具这个东西它没办法替你们团队去跟业务对口径。它也没办法替安全团队去拍板说这数据能不能出域。但是呢只要信息不再散落在每个人自己的电脑里头了。那么这个迁移就有机会从那种一次性跑完就拉倒的脚本操作变成一套可以重复跑、可以拿来审计的工程流程。每次采集它都有个身份每个问题它都知道从哪来的每次验证它都有证据。这也就是我为什么想从数据库迁移工具里头要这种确定性的原因。给任务分级才能让多人协作不互相等待迁移任务表面上看起来大家好像都管它叫“问题”。但是实际上你真要去处理的时候路径差别是很大的。我会先按它的影响范围来给它分级。而不是简单地按对象是什么类型去分组。第一类我管它叫阻塞类。什么情况呢源端你连不上采不了目标端你建不了东西核心应用也连不上。这种问题你不解决后面干啥都没意义。第二类是正确性类。就是结果集啊、事务啊或者日期和金额的口径对不上。这种就得拉业务的人来一起确认。第三类是性能类。功能跑是能跑但是关键的 SQL 一旦并发起来时间就达不到要求。第四类才轮到整理类。比如改改命名规范啊清理一下历史上没用的对象啊或者补补文档什么的。这么一分级之后呢团队每天盯着看的就不再是一张长长的失败列表了。而是一张排好优先级的工作板。搞采集的工程师他就去处理连接和权限的问题。开发人员就去处理应用 SQL 的事。DBA 呢就去审核数据库层面的语义。业务人员就负责确认结果对不对。这里要注意每一类问题都得有一个人来兜底负责。但这不等于说就他一个人在那儿干。打个比方一个报表跑出来的结果不一致。开发得去改 SQLDBA 得去查查执行路径有没有问题业务得去确认口径到底以谁为准。然后呢任务记录就把这三个人的结论给钉死在里面。对于每一个问题我都会留两个快照。一个是“首次发现快照”另一个是“关闭验证快照”。为什么要这么搞呢有一个很实在的好处。因为源端系统在迁移的时候它往往还在继续迭代。有了这两个快照团队就能分得清楚。这到底是因为旧问题你没修好呢还是因为别人新发了一个版本把新对象给带进来了。如果没有这两个版本号在那儿撑着很多时候大家讨论到最后就会变成“我那时候看见的明明不是这样啊”这就没法聊了。SELECTissue_category,risk_level,COUNT(*)ASopen_count,MIN(created_at)ASoldest_open_atFROMmigration_issueWHEREstatusIN(OPEN,IN_PROGRESS)GROUPBYissue_category,risk_levelORDERBYrisk_levelDESC,oldest_open_at;这个查询跑出来它本身不会给你下什么结论。它其实仅仅只是把那些你得优先去处理的工作给暴露在你面前而已。真要去判断风险的话你还得结合业务到底有多重要、切换窗口给的时间够不够还有出了事能不能回退这些情况来综合看。切换演练要把“回退”当成正常路径我个人的感觉是等你全量迁移弄完之后特别容易有一种错觉。什么错觉呢你会觉得既然数据都已经进到目标库里面了那切换不就是把连接串改一下嘛。其实根本不是这样。实际的切换至少要牵扯到好多事情。比如你要把写入冻结住你要把增量追平连接池的配置得更新定时的任务得停掉再起缓存得失效监控也得切过去。这里面哪怕就一步你没控住业务就可能出大问题。什么问题呢可能两边系统同时在写数据或者应用读到了不同版本的数据。这是一个很危险的情况。因为这样所以我会在正式的切换窗口之前安排一次缩短版的演练。这个演练呢它不是要你把所有的历史数据又傻乎乎地搬一遍。它是去验证那个时间顺序还有谁负责干什么的动作。谁去喊冻结谁去确认增量没了吧谁去改应用的配置谁去查核心接口通不通还有最关键的谁有权喊回退。演练完之后你得把每个时间点干了什么都给记下来。这样到了下一次你才有可能把真正的停机时间给缩短。DBA迁移团队应用负责人业务负责人DBA迁移团队应用负责人业务负责人确认写入冻结停止写入与批任务完成增量追平请求校验返回数据与对象校验结果切换目标连接并开放灰度核心交易与报表回归异常时触发回退这里边最要紧的一件事就是你得提前把回退的条件给量化了。什么叫量化呢比如你约定好连续有几个核心用例跑不通了或者关键的数据校验对不上了再或者连接报错的比例超过了大家事先说好的那个数值。这些都可以作为你要回退的信号。大家要明白回退了它不代表你这个项目就失败了。它仅仅是说这是你在做迁移设计的时候本来就该有的一种保护措施而已。让 DBA 支持沉淀为下一次的规则一说到“服务”这个环节很多人会理解歪了。觉得那就是出了故障了再去拉个专家来看看。其实更有价值的做法是什么呢是让 DBA 在评估的阶段还有跑样本的阶段就提前插手进来了。去查查那些风险高的 SQL去确认一下索引和统计信息该怎么搞去看看事务和等锁的情况怎么样。这么搞有什么好处呢好处就是等到了真正切换的那天DBA 他不是那个临时跑来救火的人。他已经是一个之前就参加过规则验证的审核者了心里是有底的。每次只要是人去处理完了一个问题我都会习惯性地问自己两个问题。第一个问题这个东西能不能把它变成一条转换规则第二个问题下一次做评估的时候能不能把它给自动识别出来如果说这两个问题的答案都是“能”。那我就把这个对象的特征、你是怎么处理的、还有你怎么验证的全写进知识库里去。如果说答案是“不能”。那也得记下来得写清楚它到底是依赖了哪一项业务语义才没法自动搞的。前面那种做法呢能让以后自动化的比例变高。后面那种做法呢能防止下一个项目把这种需要人脑判断的复杂问题当成简单的脚本来乱搞。也就是因为这个我才觉得 KDMS 搞的这个“云端服务”协同是有价值的。怎么讲呢云端它把项目整个的样子给存下来了。端侧它把现场采集这件事给控住了。DBA 的服务呢把人的经验又倒灌回了问题和规则里面去。这三边只有说它们同时把版本留了、把责任分了、把证据钉死了。这个数据库迁移工具它才不会变成那种用一次就扔的程序。它才会变成一套你能一直改、一直优化的工程方法。
返回列表