从Oracle/MySQL到瀚高数据库:迁移工具实战与避坑指南
2026/9/8 3:42:13 网站建设 项目流程

简介:这是一套面向数据库运维及开发人员的瀚高数据库迁移工具包,主要解决从 MySQL、Oracle 等异构数据库向瀚高数据库迁移时的手工建表、类型转换与数据同步难题。工具提供可视化操作界面和内置帮助文档,覆盖新建连接、迁移任务配置、表对象选择、数据类型匹配等关键环节;尤其对 datetime 与 TIMESTAMP/TIMESTAMPTZ 的转换给出了明确处理方式,并支持迁移日志查看与错误详情定位,便于实施者快速排查问题。压缩包整体约 247.77MB,采用 rar 格式封装,适合需要批量迁移或首次接触瀚高数据库的团队参考使用。已有 1819 人学习该资源,迁移实施前可先对照工具说明梳理源库类型映射,能有效降低试错成本。 前阵子接了个活儿,要把一套跑了快十年的Oracle 19c库迁到瀚高数据库上去。项目里配套的迁移工具是migration,它主要解决的是把MySQL、Oracle这类常用数据库里的结构、数据、程序对象,成体系地搬到瀚高。我一开始以为这类工具就是图形界面里点几个下一步,真跑完一轮之后才发现,做迁移最怕的不是数据搬不动,而是搬过去之后一堆对象“看起来在,跑起来错”。这篇文章我把整个实操过程和对工具机制的理解整理出来,给后面做同类型迁移的朋友一个参考。

1. 迁移的本质是“搬运”加“翻译”,工具补上了后者

1.1 手工拷表可以走通,但走不到“可上线”

大多数DBA第一次面对跨库迁移,直觉都是“把源库的表结构导成SQL脚本,到目标库里改一改类型,再把数据导过去”。这个思路对三五张表、没有复杂程序对象的场景完全够用。一旦涉及真实生产,事情就没那么简单了。Oracle一个库几百张表,再加上几十个存储过程,手工导出SQL脚本拿回来你会发现:

  • 类型定义得逐个改,改完还可能踩精度坑,比如Oracle的NUMBER不写精度,直接映射成INTEGER,大数值就溢出了。
  • 存储过程里全是PL/SQL语法,还有PACKAGE、隐含游标、%TYPE这种Oracle才有的写法,靠人肉翻译一遍非常容易漏。
  • 序列、触发器、视图、同义词、物化视图一个都不能落下,少一个,应用联调阶段就给你颜色看。
  • 数据量大时导出导入时间不可控,导到一半断掉得从头再来。

手工做的真正成本不在“搬运数据”,而在“翻译差异”。翻译漏一条,联调阶段就会冒出一堆SQL报错,那时候再回头查表结构定义、比对字段注释,非常浪费时间,而且越到项目后期越不敢动。

1.2 迁移工具的核心价值:把专家经验变成可复用的规则

migration这类工具的做法,本质上是把一个资深DBA在面对跨库迁移时的检查清单,固化成了一套自动执行的规则。你给它源库连接信息和目标库连接信息,它会自己查数据字典、生成对象清单、按映射规则生成目标端DDL,再批量搬数据。人对变化的把握强,工具对覆盖面的把握强,迁移项目真正需要的其实是“工具铺范围、人工补残局”。

我比较看重migration的一点是,它对瀚高自己的兼容模式做了配合。意思是说,工具生成的目标端脚本不一定是纯PostgreSQL方言,它知道瀚高内置了MySQL兼容、Oracle兼容的能力,所以遇到某些源库特有语法时,会优先保留原写法,交给目标库的兼容层去解析。这个设计让存储过程这类程序对象的迁移成功率提高不少,也减少了应用侧SQL的大规模重写。

2. migration工具的原理拆解:源库元数据、类型映射与语法转换

2.1 源库端:从连接信息到元数据清单

工具第一步是连接源库,从JDBC的DatabaseMetaData以及各库的系统字典里获取元数据。对Oracle来说,它会去查ALL_TAB_COLUMNS、ALL_CONSTRAINTS、ALL_INDEXES这类数据字典;对MySQL来说,它主要依赖information_schema。这里有一个容易忽略的前提:源库账号必须拥有读取这些字典的权限。我遇到过迁移账号权限只给了DML,结果工具连上了源库,但表清单全是空的,排查了半天才发现是权限问题。

还有一类情况是,某些对象信息在JDBC标准接口里拿不到,比如视图定义、存储过程源码、触发器的完整文本。这时候工具通常会退回执行语句的方式,直接从系统视图或SHOW CREATE VIEW这类命令里去抓原文。抓回来的文本再交给语法解析器去处理。所以,源库字符集设置必须正确,否则SQL文本里的中文注释、中文字段名解析出来就是乱码,迁移报告里会莫名多出一堆失败项。

2.2 目标端:类型映射与语法改写怎么工作

这是整个工具最见功力的部分。类型映射如果不合理,后面所有问题都会在数据加载甚至应用运行时才暴露出来。我拿到的版本里,MySQL和Oracle到瀚高的映射大体是下面这个样子,不同版本可能有微调,但方向是一致的。

源类型(MySQL)瀚高映射说明
TINYINTSMALLINT避免负数溢出
INTINTEGER常规整数
BIGINTBIGINT长整数
VARCHAR(n)VARCHAR(n)注意源库字符数定义是否与目标库一致
DATETIMETIMESTAMP保留时间精度
TEXTTEXT长文本
BLOBBYTEA二进制
AUTO_INCREMENTSERIAL / IDENTITY自增语义对应,但要重置序列
源类型(Oracle)瀚高映射说明
VARCHAR2(n)VARCHAR(n)字节与字符语义要确认
NUMBERNUMERIC无精度时保留大数类型最安全
NUMBER(10)INTEGER整型无歧义时可窄化
DATETIMESTAMPOracle的DATE是带时分秒的
CLOBTEXT长文本
BLOBBYTEA二进制
TIMESTAMP(n)TIMESTAMP(n)精度保留

映射规则背后其实是有取舍的。比如Oracle的NUMBER不指定精度时,我建议在目标端尽量保留为NUMERIC,而不是盲目收窄成INTEGER或BIGINT。因为NUMBER不设精度意味着理论上可以存非常大的数,收窄后一旦数据里出现大数,迁移过程直接报错,那时候回头改表结构代价很高。MySQL的DATETIME和Oracle的DATE都带时间部分,统一映射到TIMESTAMP是合理的,但如果原表里其实只用日期,映射成TIMESTAMP也不会错,只是多占一点存储。

语法改写这块,则要分两类看。一类是目标端必须写成纯PG方言的地方,一类是可以保留原方言、交给瀚高兼容层处理的地方。典型差异包括:

  • MySQL的反引号标识符。在MySQL兼容模式下,反引号可以被识别;但如果目标库是纯PG模式,就得去掉或改为标准双引号。
  • MySQL的LIMIT分页、AUTO_INCREMENT、ON DUPLICATE KEY UPDATE。
  • Oracle的ROWNUM、NVL、SYSDATE、DUAL表、CONNECT BY层级查询、外连接的(+)写法。

举一个最典型的分页SQL改写。Oracle原来的写法是:

SELECT * FROM ( SELECT t.*, ROWNUM rn FROM emp t WHERE ROWNUM <= 20 ) WHERE rn > 10;

迁移后按PG风格一般是:

SELECT * FROM emp ORDER BY emp_id LIMIT 10 OFFSET 10;

注意,ROWNUM分页在没有ORDER BY的情况下是不保证排序的,改写后如果加上ORDER BY,结果顺序可能和原库不一致,这个要业务确认。migration工具会自动做这类改写,但改写后的SQL建议人工过一遍,尤其是带复杂子查询和排序的。

2.3 迁移报告的生成逻辑:先把失败摊开,才能谈上线

工具跑完会生成一份报告,列出成功、失败、告警的对象,并附上失败原因。这是整个迁移项目里最有价值的产物。我的习惯是重点看三类:

  • 失败对象:必须人工介入处理的,比如语法解析不了的自定义函数。
  • 告警对象:工具转换了,但不确定行为是否一致的对象。比如触发器内部有复杂的嵌套逻辑时,工具虽然能生成目标端脚本,但语义是否对等要人工确认。
  • 无提示对象:不代表绝对没问题。结构能建起来,不代表性能行为和原库一致。索引缺失、统计信息没收集,都会让原本很快的SQL变慢,这一点后面会展开。

3. 一套可复用的迁移作业流程:预检、对象迁移、数据校验、切换上线

3.1 预检阶段:在点击“开始”之前,先把这些问题问清楚

磨刀不误砍柴工。预检阶段我会把下面几个问题全部过一遍,确认无误才会真正点开始迁移:

  • 源库版本和字符集是什么?版本太老、字符集是特殊编码,都会影响工具解析。
  • 迁移账号权限够不够?Oracle侧需要能查数据字典,MySQL侧需要能读information_schema,尤其是SHOW VIEW、TRIGGER权限。
  • 网络和防火墙端口通不通?源库和目标库通常不在同一台机器,特别是跨机房场景,先telnet一下端口比在工具里报错再排查要快。
  • 这次迁移范围是全库还是只迁业务schema?系统自带的schema、临时表、日志表要不要迁?建议一开始就明确,避免把一堆无用对象也搬过去。
  • 目标库初始化成什么模式?这决定了后面工具生成脚本的风格,也决定了应用SQL能保留多少原样。我建议在迁移前就让DBA把目标库按业务预期切到对应兼容模式。

这些信息问清楚以后,迁移工具的操作反而很快。

3.2 对象迁移与数据迁移:分两步走,别一把梭

我的实操顺序是:先跑结构,再搬数据,最后再建程序对象。很多人喜欢一把梭让工具把结构、数据、存储过程一次跑完,但一旦中间报错,排查范围会很大。拆开走会舒服很多:

  1. 先迁移表、序列、约束、索引这些基础结构。跑完看失败对象清单,该补的补,该手工处理的处理,确认结构层没问题再往下走。
  2. 数据迁移阶段设置好批量大小、并行任务数。批量事务太大容易把目标库的WAL撑爆,太小则速度上不去,我一般起步给5000行一批,再根据目标库负载逐步调。
  3. 程序对象放最后。存储过程、函数、触发器都引用了表结构,表还没建好就建这些一定会报错;而且程序对象经常需要多轮调整,放后面可以反复补迁移,不影响前面的数据。

数据迁移过程里,长表是最容易让人焦虑的。建议先挑一张数据量最大的表做一次小规模预跑,估一下单位时间能搬多少行,再推算全量耗时,给切换窗口留出足够余量。

3.3 校验与切换:数据比对通过不代表应用能跑

迁移完成后,第一件事不是让业务直接连上去,而是做三轮校验:

  • 行数比对。源库和目标库逐表做COUNT(*),数目不一致的表直接拉出来。
  • 抽样比对。对大表按主键抽样,比对非大字段列的值;CLOB、BLOB这类大字段单独比对长度或抽取少量样本做整体哈希。
  • 约束校验。检查主键、唯一键、外键是否有重复或失效的记录,尤其是源库本身约束不严、历史数据里已经混进脏数据的时候。

即使这三轮全过,我也不会直接宣布切换完成。因为数据全对,不代表应用能跑。索引缺失、统计信息没收集、函数行为有细微差异,都可能让原来毫秒级的查询变成秒级。所以切换前一定要从源库抓一批TOP SQL,到目标库上回归一遍,重点看执行计划和耗时。

切换窗口则按“停写-增量补数-再比对-切应用连接”的顺序走。如果是数据量不大的业务,停写之后做一次最终增量同步,应用改个连接串就能切过去;数据量大的,需要更细的增量方案,这里不展开。

4. Oracle和MySQL迁移到瀚高时,最容易翻车的细节

4.1 Oracle侧:存储过程、序列、ROWNUM与特殊表

Oracle迁移到瀚高的难点,本质上就是Oracle和PostgreSQL系语法的差异。最容易翻车的是这几块:

存储过程。PL/SQL和PL/pgSQL语法有差异,比如Oracle的%TYPE、%ROWTYPE、内置异常名、DBMS_OUTPUT包,在PG风格里都不直接存在。工具能覆盖一半左右的模式化写法,但复杂逻辑最好提前评估人工成本。一个常见对策是,如果目标库开了Oracle兼容模式,很多存储过程能直接建上,但碰到包(PACKAGE)这类Oracle强特性,兼容模式也救不了,必须做代码改造。

序列。Oracle的SEQUENCE在迁移后一般映射成PG的SEQUENCE,但应用里如果大量使用序列名.NEXTVAL,要注意目标库里序列的当前值是否设置了正确起始点。数据迁移完成后,如果序列起点还在1,业务一插入就会主键冲突。正确做法是把序列值重置到max(主键)+1

ROWNUM分页。前面SQL改写里提过,工具能改掉语法,但改不掉业务对“无排序分页结果稳定”的错误依赖,这种问题只能靠应用层改代码。

还有两类Oracle特殊对象要提前盘一下:同义词(SYNONYM)和物化视图。同义词在目标端一般没有完全对等的概念,物化视图则要确认刷新机制,工具未必能自动处理,项目计划里要留出人工量。

4.2 MySQL侧:自增列、反引号与保留字

MySQL迁移到瀚高相对温和,但也有几个隐蔽问题。

自增列。MySQL的AUTO_INCREMENT在瀚高里映射成SERIAL或IDENTITY列,结构能建,数据能搬,但搬完之后序列的当前值不会自动等于max(id)+1。这个坑很多人在第二天业务插入时才意识到,处理方式同样是迁移完成后重置序列。

反引号。MySQL的建表语句和SQL里大量使用反引号包标识符,如果目标库没开MySQL兼容模式,这些反引号要么被工具去掉,要么得改成双引号。开了兼容模式则可以保留原样,但反引号在跨库工具里容易引起解析歧义,我见过工具把反引号里的内容识别成字符串导致表名变小写的情况,所以迁移后要抽查几个对象的名称是否和预期一致。

保留字。MySQL里很多表名、字段名用了order、group、desc这类保留字,源库用反引号包着没事,迁到目标库后如果没做处理,SQL执行就直接报语法错误。迁移后用schema比对工具扫一遍对象名,比人工挑靠谱。

4.3 数据层的坑:字符集、精度与大字段

字符集是最早暴露问题的地方。MySQL的UTF8MB4和PG/瀚高的UTF8并不是完全一致的,某些4字节生僻字在UTF8MB4下能存,迁到只支持UTF8的库就报编码错误。预检阶段就用工具扫一遍源库有没有超过3字节的字符,能省很多事。

精度问题在Oracle侧更常见。Oracle的NUMBER可以存到38位十进制数,MySQL的DECIMAL可以到65位,如果映射规则是把这些“大数类型”统一收窄成BIGINT或DOUBLE,价值大于15位的尾数就会出现精度丢失。所以我在映射规则里对这类字段一律不窄化,保留足够宽度,宁多勿缺。

大字段的搬迁速度也是要提前压测的。大量CLOB/BLOB的字段在JDBC模式下传输,如果批量参数设置不当,整体耗时会成倍增加。实操中可以先按主键范围分段迁移,配合大字段流式读写方式,避免一次性把大对象读进内存。拿一张典型大字段表先跑个小范围,估算出单位时间吞吐量,再决定全量并行度。

5. 周边适配踩坑记录:兼容模式切换、Navicat连接与Windows环境

5.1 兼容模式是什么,切换后到底变了什么

很多人第一次听“瀚高数据库切换MySQL模式”会以为是要重装一个数据库,其实不是。瀚高基于PostgreSQL内核,兼容模式可以理解成内置的方言开关。切到MySQL模式后,解析器能识别MySQL的反引号、AUTO_INCREMENT写法、CURRENT_TIMESTAMP默认值这些常见能力;切到Oracle模式后,识别PL/SQL存储过程语法、DUAL表、NVL这类Oracle函数就顺理成章。

migration工具和兼容模式是搭配使用的。工具在转换时知道目标库开了什么模式,遇到源库特有语法时它会选择“保留原样交给兼容层”,而不是强行改写。这个策略的优点是应用SQL改动少,缺点是兼容模式不是100%覆盖,总有一些冷门语法需要人工兜底。所以我在迁移前会先做一轮SQL文本扫描,把应用里对MySQL/Oracle特有函数的依赖程度摸清楚,再决定目标库用哪个模式。如果应用本来就在向标准SQL靠拢,那兼容模式只作为过渡期兜底,目标还是统一成PG方言。

5.2 Navicat连接瀚高数据库:比想象中顺利,但有一个细节要注意

因为瀚高的通信协议走的是PostgreSQL协议,所以Navicat建连接时直接选PostgreSQL类型就行,不需要额外装驱动。这个对团队来说挺友好,很多同事已经在用Navicat,不需要为了迁移再换一套工具。

但有两个细节容易卡住人。第一,端口别背默认值,装好后去数据库配置文件里确认实际端口,不同版本、不同发行包可能不一样。第二,用户和库名要注意大小写。PG语义下,不带引号的标识符会转换成小写,如果你在瀚高里创建的库名带大写字母,连接串里就要加双引号,否则连不上或连到别的库。还有一个容易懵的点是,连接后看到的是和用户名同名的schema,表不在public下,而是在这个同名schema下,别到处找不到表。

5.3 Windows环境快速验证与生产环境的取舍

如果要快速验证migration工具的迁移效果,用Windows环境做一次全流程演练是非常高效的。下载Windows版安装包,起服务,用图形界面把迁移跑通,比在Linux上折腾各种依赖快得多,特别适合做概念验证、脚本验证和给团队做演示。我在前期评估阶段就是这么干的,短短一周就把源库表结构、数据迁移、存储过程改造这些关键场景全部验证了一遍。

但如果要上生产,我还是建议用Linux环境。倒不是说Windows跑不了,而是生产环境下数据库运维的很多默认手段,比如备份恢复脚本、监控采集、内核参数调整,都优先围绕Linux生态展开。Windows环境更适合做“这条路走得通”的证明,而稳定性和长期维护,Linux更让人放心。

最后分享一个我自己的经验。如果你也正在拿migration工具做评估,我建议先别急着迁核心业务表,挑一个包含存储过程和自增主键的小业务先跑通全流程,把时间估算、失败对象、序列重置这几个关键点摸清楚,再放大到全量。迁移工具不复杂,复杂的是对差异的敬畏,提前在测试环境把所有问题暴露一遍,切换那天就不会太难堪。

本文还有配套的精品资源,点击获取

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

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

立即咨询