迁移评估不再拍脑袋,这个数据迁移工具的量化报告把我救了(上)

做数据库替换的人,最怕的问题不是"怎么迁",是"你敢不敢给个数"。工期多少,风险在哪,哪些对象要改,改多少。以前这些问题我全靠经验估,估完自己心里都发虚。直到最近用上数据迁移工具 KDMS 做了一轮正经的迁移前评估,才头一回拿到一份能量化的报告,兼容度多少,不兼容多少处,分布在哪些对象类型上,全都列出来。这上下两篇就聊聊我这次评估的完整过程,上篇讲采集,下篇讲报告本身和怎么用它做决策,写的时候想到哪说到哪,可能有点乱,凑合看。

先把痛点说透,不然有人觉得评估就是个走过场。

评估难到底难在哪

我干替换项目四五年,每次立项会都是同一个剧本。业务方问,这个库迁过去,要多久。我说得看对象复杂度。对方追问,多复杂。我说几百个存储过程,里面啥写法都有。对方再问,那到底几个人几周。到这一步我就开始编了。拍个脑袋,报三个月,心里想的是最好能拖到四个月。

问题出在哪。出在没数据。你手里只有一堆模糊的印象,这个库挺老的,存储过程挺多的,有几段代码特别恶心。印象没法拿去排期,更没法拿去扛责任。有次我报了三个月,做到第二个月发现有个排产过程两千三百行,游标套游标,中间还夹着动态 SQL 拼 MERGE,光理清主干就花了两天。那项目最后超期了,超期的原因复盘来复盘去,就是评估阶段根本不知道库里有这种货色。

这事还牵扯到一个更麻烦的点,就是兼容这个词本身。

兼容度这个词,先得掰扯清楚

市面上一说国产库兼容 Oracle 兼容 MySQL,听着都挺唬人,但兼容度到底怎么算出来的,各家口径不一样。我在论坛上翻过不少帖子,同一个库,有人说兼容度九十多,有人说不兼容的地方多得吓人,吵得不可开交。后来我琢磨明白了,不是谁撒谎,是大家量的东西不在一层。

我自己习惯把兼容掰成三层看。最底下一层是"建得起来",DDL 能跑,对象能创建,存储过程能编译通过。中间一层是"跑得对",语义等价,结果跟原来一模一样。最上面一层是"跑得快",性能不掉链子。

工具类评估,包括 KDMS 这种,能量化的其实主要是第一层。它把源库对象抓过来,在目标库上做转换和编译验证,编译过了算兼容,编译报错算不兼容。这个界定不完美,我很清楚它的局限,第二层的语义等价它测不了,比如两个函数空值处理行为差一点点,语法上谁都没错,结果就是对不上。第三层性能更不用想,评估环境里根本没有真实流量。

但话说回来,第一层难道就没价值吗。不是的。我宁可要一个明明白白的第一层数字,也不要一句"基本兼容,问题不大"。前者我至少知道有多少对象连编译都过不去,后者就是一句空话。所以我对评估工具的定位一直很明确,它给不了全部真相,但它能把最硬的那部分骨头先啃出来,剩下的靠人工补。

这个认知是吃亏吃出来的。而且这个界定本身还有个绕不开的问题,评估工具算兼容度的时候,分子分母怎么定,是按对象个数算,还是按 SQL 语句条数算。同样一个库,一百个表一个不兼容,十个过程五个不兼容,按对象算兼容度 95%,按过程这个维度看就只剩一半了。数字这个东西,算法一变,面貌全变。所以后面看到报告里的百分比,我的习惯是先翻到明细去看统计口径,分类型看了心里才踏实。这个后面还会提。

往下倒几年,这活儿全靠手工。

早几年怎么评估,时间线捋一捋

最早那会儿,大概五六年前,没人拿工具评估。大家的办法土得掉渣。连上源库,把 dba_objects 之类的视图查一遍,数一数有多少表多少过程,Excel 里一填。然后 grep 关键字,Oracle 的库就搜 MERGE、ROWNUM、CONNECT BY 出现次数,MySQL 的库就搜 ON DUPLICATE KEY、GROUP_CONCAT,数出来个大概,乘以一个拍脑袋系数,就是工期。

sql 复制代码
-- 那时候的土办法,大概长这样
SELECT object_type, COUNT(*) AS cnt
FROM dba_objects
WHERE owner = 'MYTEST'
GROUP BY object_type
ORDER BY cnt DESC;

这个方法的毛病显而易见,只数了数量,没看内容。三百个存储过程和三百个存储过程,难度能差十倍,关键看里面写了啥。而且那时候的统计粒度也糙,表和过程混在一个数里,你没法回答"不兼容的都在哪类对象上"这种问题。业务方其实就要这么个答案,表好办还是过程好办,直接决定改造重点压在 DBA 身上还是压在开发身上。土办法给不出,只能含糊说都有一些。这种含糊在立项会上就是被追着打的软肋。

后来大家学聪明了,开始抽样,把存储过程按行数排序,挑最长的十个打开人工看。

sql 复制代码
-- 按行数排序找硬骨头,这个土办法我到现在还留着
SELECT name, line
FROM dba_source
WHERE owner = 'MYTEST'
GROUP BY name
ORDER BY line DESC
FETCH FIRST 10 ROWS ONLY;

这招我到现在还在用,说实话某些时候比工具的数字还准,因为你看到的是真实的代码长相,恶心程度一目了然。但抽样的软肋同样明显,看十个未必代表三百个,万一第十一行开始全是另一种流派呢。统计学的常识,样本外的风险永远存在。所以土办法和工具不是替代关系,是互为补充,工具给全量,人去看典型。

再往后,厂商们开始做工具化的评估。这背后有个大势,替换项目多了,实施团队就那几个人,不可能每个项目都扑上去人工数对象。工具化的思路也分两派,一派是做静态扫描,扫代码扫对象出报告,另一派偏重在线测试,拿一堆典型 SQL 到目标库上跑分。两派各有道理也各有盲区,静态扫描覆盖全但深度浅,在线测试深度够但样本有限。论坛上这俩路线的支持者也吵,我的看法是别二选一,覆盖面的问题用扫描解决,关键路径用测试解决,评估报告只是起点不是终点。

KDMS 走的是前一条路线,采集加静态评估。全名挺长,叫金仓数据库迁移评估系统,下面我全用简称。它整体分三块,数据库采集,应用采集,兼容度评估。这个产品定位说白了就是把评估这步从"老师傅带徒弟"变成"人人可复制的流程",老师傅的经验编码成了采集范围和评估规则,换个新人来也能跑出一份像样的报告。当然报告的解读还是得靠人,这是后面下篇要说的重点。下面挨个说我上手的体验。

部署:比想象中轻

先说部署。这东西跑在 Linux 上,资源要求不算高,内存 16G,软件包占 2G 磁盘,安装路径再留 5G,就这些。我们拿了一台虚拟机就装了。建议用独立账号跑,别拿 root 或者公用账号凑合。

bash 复制代码
shell# adduser kdms
shell# su - kdms

有个小坑提醒下,默认安装目录是 /opt/KDMS,你要直接用 kdms 这个用户装,装到一半会提示没权限,因为 /opt 下建目录的权限不在它手里,得提前把目录授权给这个用户。访问端口默认 19007,跟机器上已有的服务撞了的话,安装过程中可以改。装完先做个功能验证,看下日志,别急着连生产。

整体感觉这工具不是那种笨重的企业软件,采集端和评估端是分开的,采集客户端可以放到源库那边的机器上跑,评估系统单独部署。这个分离设计后面会说到它的好处。

好处其实一句话就能说明白,采集包是隔空传话的载体。很多替换项目,源库在内网 A 区,评估的机器在 B 区,中间隔着防火墙甚至物理隔离,你不可能让评估系统直连生产库。分离之后,采集器进 A 区拿包,人把 zip 拷出来,传到 B 区的评估系统上传,链路就通了。数据不出区,包能出区,安全部门那边也好交代。要是评估系统直连源库的方案,光安全评审就能卡你半个月。我这次是测试环境无所谓,真到生产那就是另一套流程了,所以提前把这种架构跑熟是有意义的。

采集:结构信息,不碰业务数据

重点说说采集,这是评估的地基。地基歪了后面全歪。

先说让我最安心的一条,KDMS 的数据库采集只抓结构信息,表、视图、触发器、约束、序列、函数、存储过程这些的 DDL,不读业务数据。对生产库来说这点太重要了。你想想评估阶段就要连生产库,DBA 第一个问题就是会不会影响业务,会不会拖数据出来。只采结构这个答案能把 DBA 的戒心放下一大半。哦对了,它还有个可选项,能顺手采每张表有多少条数据、占多大磁盘空间,这个是统计信息,也不碰数据本身,后面评估概要里会用到。

采集用户也别用业务账号。手册里明确建议建临时采集用户,采完就删。Oracle 这边我实际用的授权,大概这么一堆。

sql 复制代码
-- 建采集用户,给权限,采完删掉
create user KINGBASE_USER identified by "kingbasePASSWORD"
    default tablespace USERS;

grant connect, resource, select_catalog_role,
      select any dictionary to KINGBASE_USER;
grant execute on DBMS_LOGMNR to KINGBASE_USER;
grant execute on dbms_metadata to KINGBASE_USER;
grant select any transaction to KINGBASE_USER;
grant analyze any to KINGBASE_USER;
grant EXP_FULL_DATABASE to KINGBASE_USER;

能看到这些权限对应啥吗。DBMS_LOGMNR 是挖日志的,DBMS_METADATA 是抽对象 DDL 的,EXP_FULL_DATABASE 是为了采 DBLINK 结构。每个权限都有明确的用途,这点我喜欢,不是让你直接 root 级别梭哈。要是 Oracle 12c 的 CDB 架构,还有点麻烦,得连到 CDB 上建 COMMON USER,用户名得带 c## 前缀,授权全要加 container=all,踩过一次坑就记住了。

sql 复制代码
-- 12c CDB 模式,用户名前缀 c## 不能少
create user c##KINGBASE_USER identified by "kingbasePASSWORD"
    default tablespace USERS;
grant connect, resource, select_catalog_role,
      select any dictionary to c##KINGBASE_USER container=all;
grant execute on dbms_metadata to c##KINGBASE_USER container=all;
grant select any table to c##KINGBASE_USER container=all;

支持的源库类型,Oracle、DB2、MySQL、SQL Server、Sybase,主流的都覆盖了。新建采集的时候填 IP 端口用户密码,然后选对象类型。Oracle 那边能选的对象类型列出来感受下,INDEX、SEQUENCE、SYNONYM、TABLE、VIEW、MATERIALIZED VIEW、TYPE、TYPE BODY、FUNCTION、PACKAGE、PACKAGE BODY、PROCEDURE、TRIGGER、DATABASE LINK、JOB、CONTEXT。十六种,比我手工评估时看的全。以前我就看表和过程,SYNONYM 和 TYPE 这些经常漏,漏了之后迁移时就出幺蛾子。

有个细节,Oracle 填 SID 还是服务名,RAC 环境必须选服务名,填 Schema 的时候注意大小写。这种小地方手册里都会提一句,但真上手的时候十个人有八个第一次就栽在这,我算其中一个。还有采集耗时的事,我这个测试库两千来个对象,从开始到采集完成一分半钟,进度条到 100% 就能下载采集包了。包很小,压缩前不到 1M。当然这是结构信息的量级,要是勾了数据量统计会稍微大一点,但也就几十 M 的级别,跟数据本身比可以忽略。别小看这点,有的评估方案要把数据导出来搭影子库再测,几 T 的库光倒腾一遍就得几天,评估还没开始成本先堆上去了。

顺便说下采集包里的结构。解压开是个按时间戳命名的文件夹,里面是各对象的 DDL 文件,再配上前面说的那个 meta 文件。这里有个坑,COLLECTOR_META.dat 记录了这次采集的元信息,建评估项目的时候要校验它,不存在或者不合法就建不了。所以不同库的采集包别混着用,也别拿一个 meta 文件到处复制,老老实实一次采集一个包。我一开始没当回事,两个库的包放一个目录里改名混用,结果建评估项目直接报错,翻日志才发现是 meta 校验没过。规矩就是规矩,人家这么设计也是为了防止张冠李戴,评估一个库的结果挂在另一个库头上,那报告就成废纸了。

历史SQL采集:从 shared pool 里捞真实语句

上面说的是对象采集,评估的是库里"住着"的东西。但还有一类东西对象采集看不见,就是应用实际跑的 SQL。老系统的 SQL 一半在存储过程里,还有一大半在应用代码里拼着,光看库不知道业务到底怎么用它。

KDMS 给了两条路补这块。一个叫历史 SQL 采集,原理挺有意思,走 Oracle 的 v$sqlarea 视图。

sql 复制代码
-- 采集器本质上是查这个视图,字段说明
SELECT SQL_FULLTEXT,     -- SQL 完整文本,含绑定变量
       LOADS,            -- 加载进共享池的次数
       LAST_ACTIVE_TIME, -- 最后活动时间,用它控制采集范围
       COMMAND_TYPE,     -- 语句类型 SELECT/INSERT/...
       PARSING_SCHEMA_NAME -- 执行时用的模式名
FROM v$sqlarea;

这个视图持续跟踪 shared pool 里所有共享 cursor,跑过的 SQL 基本都在里面躺着。好处是不用改应用不用重启,坏处也明显,shared pool 是滚动的,老 SQL 会被挤出去,所以得定期采,LAST_ACTIVE_TIME 就是拿来圈时间范围的。这个思路不是它一家独有,但做成工具自动跑确实省事。

采这个有什么用,我举自己的例子。有个老系统,库里的存储过程看着风平浪静,评估兼容度也高,但业务方死活不敢说应用不用改。为什么,因为应用里 Mybatis 拼的 SQL 有一千多句,全在 java 代码和 xml 里,你评估库对象等于只看了半张地图。这时候历史 SQL 采集就顶用了,把 shared pool 里捞出来的真实语句跑一遍评估,哪些写法在目标库上会翻车,列得清清楚楚。比翻代码一页页人肉看强太多。当然它也有覆盖盲区,刚跑完一批不常见的报表 SQL,shared pool 还没来得及淘汰,正好在你采集窗口里,它就被抓到了,反过来错过窗口的就成了漏网之鱼。所以真要较真,就得在业务高峰后采一次,月底结账后再采一次,多采几轮拼全貌。

另一条路是应用采集,分静态和动态。静态的扫代码,把 Java 项目里的 Mapper xml 文件和 SQL 脚本打包成 zip 传上去,选好语法类型就开扫。动态的更狠,挂到运行中的应用上,采实际执行的 SQL 加调用堆栈。我这次只试了静态的 Mapper 扫描,动态那个需要在应用侧动东西,得开发配合,评估阶段还没走到那步。

踩坑记录

采集环节报错不少,捡几个典型的。先说结论,这环节的报错九成都是环境和权限问题,跟工具本身关系不大,但每个都得耗你一阵。Oracle 那边最容易碰 insufficient privileges,就是采集用户权限没给够,回去对着授权清单补,补完重试就好,最气的是它不会一次告诉你要哪些权限,缺一个报一个。MySQL 那边我碰到过两次报错,一次是 Latin1 is not supported,字符集的事,源库建库用了 latin1,得先统一到 utf8 再采,这个没绕的办法,老库改字符集本身就是个课题。另一次是 CLIENT_PLUGIN_AUTH is required,这个是驱动版本对不上,老驱动连新协议不支持,换个高版本的驱动包就好了。SQL Server 的坑更刁钻,连接报 18456 登录失败,查了半天发现是实例认证模式的问题,改完又冒出来一个 SetARITHABORT 不正确,执行采集语句前得把 ARITHABORT 设置对齐,还有个"备份集中的数据库备份与现有的数据库不同"的报错,那是拿错备份还原的库,元数据对不上,这种属于自己坑自己。一个个都解决了,但过程确实烦,建议采集前先拿个小库把流程走通,别一上来就连生产。

测试连接失败这种通用报错就不用说了,先查网络和端口。

采集完就到评估了。把采集包上传,系统自动识别出源库类型和兼容模式,评估名称带出来可以改,然后选目标版本,点确认,评估任务就跑起来了。如果部署的时候装了评估插件,采集完成页面上会直接给个"立即评估"按钮,一步到位,省得下载再上传那个 zip。

采完了顺手还试了个小功能,在线评估。评估菜单下面单独一个入口,进去就是一个 SQL 编辑页,选好目标版本和兼容模式,把一句话贴进去,立刻告诉你这句在目标库上能不能跑。这功能看着不起眼,评审会上特别好使。有次开发质疑某个写法迁过去行不行,我当场贴进去跑给他看,比嘴上争十分钟管用。当然它也是只验编译不验语义,这个前面说过的局限在这里同样成立,别迷信。

评估跑完进详情页,第一眼看到概要,兼容数量,不兼容数量,还有一个大大的兼容度百分比。我看到那个数字的第一反应不是高兴,是犯嘀咕,这数字怎么算的,可信吗,能直接拿去汇报吗。

而且这轮评估我还发现一个此前没细想的点,评估对象是死的,人是活的。同一个库,这周采一遍和下周采一遍,结果可能就不一样,因为开发可能又改了两个过程。评估报告是有时效的快照,不是一锤定音的判决书。所以我的做法是把评估放在对象冻结之后,跟开发约好,评估窗口期内谁也别动库,评估完再解冻。这么点小事,但它决定了报告的严肃性。

这些疑问的答案,还有那份评估报告到底长啥样、细到什么程度、怎么拿它算工作量,放下篇细说。采集这块最后再啰嗦一句,临时用户采完记得删,别嫌麻烦,留着就是留风险。

相关推荐
阿狗童鞋2 小时前
Redis实战指南
数据库·redis·缓存
lupai3 小时前
维修保养记录精准版 API 对接实战指南
数据库·python
2601_952196366 小时前
计算机科学与技术专业应届生投商业分析岗,需要哪些额外能力?
数据库·oracle
皮皮学姐分享-ppx6 小时前
地级市、省级人才政策强度测算(2000-2025)
大数据·数据库·人工智能·百度·高考
晚安日记wanna6 小时前
大厂禁 JOIN 的真正原因,拆到第四层才清楚
数据库·后端·面试
java1234_小锋6 小时前
Redis 宣布正式接入 AI
数据库·人工智能·redis
这个DBA有点耶6 小时前
数据融合平台的下一代形态:数据库内核自己就能融合,为什么还要ETL?
数据库·架构·aigc
数据库小学妹7 小时前
MySQL大表怎么优化?2亿行表的分区归档与冷热分离实战
数据库·mysql·分库分表·分区表·数据库运维·冷热分离
91刘仁德7 小时前
RAG实战 - 向量数据库(Milvus)
数据库·milvus