Navicat Premium实战:Oracle到MySQL迁移全流程指南
2026/9/7 21:24:23 网站建设 项目流程

做了这么多年数据库相关的活儿,跨库迁移是绕不开的一个坎。尤其是Oracle往MySQL迁,项目背景五花八门:有的是集团统建系统要下沉到本地化部署,有的是为了降成本从商业数据库切到开源栈,还有的是数据仓库前置库要换成轻量方案。我最近正好用Navicat Premium完整做了一次Oracle到MySQL的数据迁移,整个过程踩了不少坑,也总结了一套相对靠谱的流程。这篇就按实际操盘的顺序,把从选型、预检、表结构转换、数据灌入到事后校验的完整过程写出来,给同样要干这活的朋友一个参考。

整个迁移用到的核心工具就是Navicat Premium,它内置的“数据传输”功能可以直接在Oracle和MySQL之间建通道,不需要先导出成中间文件再导进来,省了很多事。不过工具只是省力,真正决定迁移质量的还是前期准备和对两个数据库差异的理解。下面逐一展开。

1. 迁移方案选型与整体设计思路

1.1 为什么用Navicat Premium而非手工或命令行

先说结论:如果是一次性的、数据量在GB级别以下、表结构不算特别变态的迁移,Navicat Premium基本是最省心的选择。

有人会问,直接用Oracle的expdp导出dmp,再用MySQL的source导入不行吗?理论上行,但实操很痛苦。dmp是Oracle私有二进制格式,MySQL根本不认,中间还得再过一层SQL解析转换。更麻烦的是,Oracle和MySQL的SQL方言差异不小,字段类型、函数、日期处理、保留字都不一样,直接灌SQL脚本大概率在第一个CREATE TABLE就报错。

命令行方案(比如写Python脚本用cx_Oracle和pymysql逐表读再写)灵活度高,但代码量大,调试成本高,而且对非开发背景的DBA不友好。我自己也写过类似的脚本,最后发现大部分时间都花在了类型映射和特殊字符清洗上,纯属重复造轮子。

Navicat Premium的“数据传输”工具把这条链路简化成了三步:配好两个连接、勾选要迁移的表、点开始。它内部会做类型映射、批量提交、错误跳过这些事,对绝大多数场景够用了。而且它支持在迁移前预览和修改字段映射关系,等于给了你一层保险,发现问题可以在启动前就调整。

1.2 迁移链路的整体架构与前置条件

这次迁移的目标库是MySQL 8.0(InnoDB引擎,utf8mb4字符集),源库是Oracle 11g R2(生产库,数据量约300G,单表最大的在1.2亿行左右)。链路是:Oracle实例 → Navicat Premium客户端 → MySQL实例,网络走的是内网专线。

这里有个关键点:Navicat Premium只是一个客户端工具,它不负责“搬运”数据文件,而是逐条把源库的数据SELECT出来,再INSERT到目标库。所以它的性能上限受两个因素制约:一是客户端机器到两个数据库的网络带宽和延迟,二是客户端本身的单线程处理能力。大表的迁移速度不会特别快,但胜在稳定可控,出错了能断点续跑(其实Navicat没有真正意义的断点续跑,但可以按条件分批续传,后面细说)。

前置条件里,最容易被忽略的是Oracle客户端的OCI库。Navicat Premium连接Oracle不是纯JDBC直连,而是通过本机的Oracle Instant Client(或者完整版Oracle Client)提供的OCI接口。机器上没装OCI的话,连接测试会直接报错。我第一次用Mac版Navicat连Oracle时就被这个坑过,后来装了对应架构的Instant Client并配好环境变量才通。

MySQL这边相对简单,官方Connector/C是Navicat自带的,基本不用额外配置。只要MySQL实例开了远程访问权限,创建一个有建库建表权限的账号就行。

2. 迁移前的预检与准备:这些事没做,后面全是坑

2.1 源库与目标库的权限、版本、字符集核对

迁移前一定要先做一轮体检,别拿到库就开始导。我一般按这个顺序检查:

  • 版本确认:Oracle 11g和MySQL 8.0之间的类型映射是最成熟的,如果是Oracle 19c或者MySQL 5.7/5.6,个别映射会有差异,需要提前看Navicat的映射规则。
  • 权限确认:Oracle侧需要能读取数据字典视图(DBA_TABLES、DBA_TAB_COLUMNS等)的权限,实际迁移时至少要有SELECT ANY TABLE的权限,否则非当前Schema的表虽然能看到名字,但查询时直接报ORA-00942。如果表是别人Schema下的,还需要GRANT SELECT权限。MySQL侧需要有CREATE、ALTER、INSERT、DELETE、INDEX权限,如果走数据传输里的“删除目标表”选项,最好再给个DROP权限。
  • 字符集:数据库迁移最怕乱码。Oracle库查一下NLS_CHARACTERSET,如果是ZHS16GBK,而MySQL目标库是utf8mb4,中文和生僻字(比如GBK里没有的emoji)都有可能出问题。稳妥的做法是MySQL侧建库时直接指定utf8mb4,Navicat会在迁移时做字符集转换。
  • 目标库预处理:在MySQL里先手工建好目标数据库,并指定字符集和排序规则。我习惯用:
CREATE DATABASE target_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

注意:排序规则别用utf8mb4_general_ci,虽然它排序快一些,但对中文和特殊字符的处理不如utf8mb4_unicode_ci严谨。如果后续要做全文索引,utf8mb4_unicode_ci也兼容性更好。

2.2 表清单梳理与大表、无主键表标记

拿到源库后,建议先跑一遍元数据查询,把要迁移的表清单拉出来。Navicat里的“数据传输”能自动列出所有表,但手工做一张Excel清单更利于把控进度,尤其是在表数量上百的时候。

我的做法是查Oracle的数据字典,把表名、行数估算值(NUM_ROWS)、是否分区、是否有主键、最大字段类型都记下来:

SELECT table_name, num_rows, partitioned FROM all_tables WHERE owner = 'SOURCE_SCHEMA' ORDER BY num_rows DESC;

这张清单的核心作用是帮你提前识别两类风险表:

一是大表(行数超过千万)。这类表在Navicat传输时建议单独勾选,不跟小表混在一起跑,否则中途某个小表报错会导致整个批次失败回滚,浪费时间。

二是无主键或无唯一索引的表。MySQL的复制、binlog、甚至后续的增量同步都依赖主键,如果源表没主键,迁移过去后建议在MySQL侧补一个自增ID,不然后续做数据比对、增量更新时会非常痛苦。

2.3 磁盘空间与网络带宽预估

这是一个经常被忽视的环节。Oracle数据文件300G,不代表你MySQL目标库只需要300G。MySQL的InnoDB引擎表数据和索引存储在一起,但碎片率、列格式(DYNAMIC还是COMPACT)、字符集转换后的字节数增长,都会让实际占用比源库更大。中文从ZHS16GBK(2字节)转成utf8mb4(3字节),光这一项数据体积就可能膨胀50%。

另外,Navicat做数据传输时,客户端所在机器会充当数据中转站,不需要额外的磁盘空间存储中间文件(它走的是内存流),但如果是用“转储SQL文件”再导入的方式,那中间SQL文件的大小就非常可观了,甚至可能达到源库大小的1.5到2倍。所以能用“数据传输”直连就不要先导出再导入。

网络带宽上,千兆内网环境下,Navicat的传输速度大概能跑到50MB/s到100MB/s,300G的数据按这个速度算,纯数据迁移时间大约在1到1.5小时之间。但如果客户端和数据库之间跨公网或者带宽有限,传输时间会成倍增加,这种情况建议先做一次小表试迁移来估算速度。

3. 表结构迁移与数据类型映射:Oracle和MySQL的“翻译官”

3.1 Navicat自动迁移的默认映射规则

Navicat的数据传输工具在勾选“创建表”选项后,会读取源表的DDL,然后按内置规则翻译成MySQL的CREATE TABLE语句。默认映射大致如下:

Oracle类型MySQL类型说明
VARCHAR2(n)VARCHAR(n)字符语义一致,直接映射
NVARCHAR2(n)VARCHAR(n)注意字符集,NVARCHAR2是Unicode语义
NUMBER(p, s)DECIMAL(p, s)p>18时会映射成DECIMAL,注意精度
NUMBER(1)TINYINT(1)MySQL里TINYINT(1)经常被当布尔用,业务侧要注意
NUMBER(10)INT / INTEGER只要p在INT范围内就映射成INT
NUMBER(19)BIGINT19位就是BIGINT上限
DATEDATETIMEOracle的DATE含时分秒,MySQL的DATE只有日期,必须用DATETIME
TIMESTAMPTIMESTAMP但默认值和时区处理逻辑不同
CLOBLONGTEXT4GB上限,一般够用
BLOBLONGBLOB二进制大对象直接对位
RAW(n)VARBINARY(n)字节流,注意长度单位
FLOAT(b)FLOAT / DOUBLE二进制精度可能变化
LONGLONGTEXTOracle的LONG是历史遗留类型,映射没问题但有兼容性风险
ROWID不支持需要手工去掉,ROWID没有实际业务意义

3.2 默认映射的“坑”与手工修正

默认映射看着挺美好,但实际跑出来往往有几个地方要手工调整。

第一个坑:NUMBER(p, s)带s的情况。Oracle里NUMBER(10, 2)表示总长度10位、小数位2位,MySQL映射成DECIMAL(10, 2)没问题。但Oracle允许NUMBER(38),也就是最大38位精度的数字,MySQL的DECIMAL最高只支持65位,但Navicat可能直接映射成DECIMAL(38, 0),这就把小数位丢了。如果源表里有NUMBER(38, 6)这种定义,一定要在映射界面手动改成DECIMAL(38, 6),否则数据精度会丢,而且不会报错——这是最危险的静默错误。

第二个坑:Oracle的DATE类型。这个我特别想强调,Oracle的DATE实际上是一个包含时分秒的日期时间类型,用法上等同于MySQL的DATETIME。Navicat默认把它映射成DATETIME,这个是对的。怕就怕有人手工改成DATE,迁移后所有的时间字段都变成00:00:00,业务直接崩。我自己遇到过这个问题,排查了半天才发现是目标表结构被手工改过。

第三个坑:CLOB字段的迁移方式。Oracle的CLOB在Navicat里默认映射成LONGTEXT,单值大小上限4GB,一般不会超出。但CLOB的读取和写入走的是LOB定位器,Navicat在批量提交时如果遇到超大CLOB(几百MB级别的XML或JSON),可能会把整个事务撑爆。所以含CLOB的大表,建议在传输选项里把“每次批处理的行数”调小一些,比如从默认的1000降到100,避免单批数据体积过大。

3.3 索引、约束和自增序列怎么处理

Navicat在创建目标表时,会连带创建主键和普通索引。但有两个东西它默认不做,需要你手工补:

一是Oracle的SEQUENCE转MySQL的AUTO_INCREMENT。Oracle表的主键通常来自序列(比如SEQ_USER_ID.NEXTVAL),迁移后MySQL表结构里不会有AUTO_INCREMENT属性。处理方法是:在MySQL目标表上手工修改主键列为自增:

ALTER TABLE user_info MODIFY COLUMN id BIGINT NOT NULL AUTO_INCREMENT;

然后把自增起始值设置成源表当前最大ID加1:

ALTER TABLE user_info AUTO_INCREMENT = 1000001;

如果不做这一步,业务新增数据时主键就可能冲突,特别是应用代码里还残留着Oracle的序列调用逻辑的话(比如直接用SELECT SEQ.NEXTVAL FROM DUAL去取新ID),那在MySQL里会直接报错,等于逼着业务侧改代码。

二是Oracle的触发器(Trigger)。如果你迁移的库里有大量用于维护审计字段、复杂默认值的触发器,它们不会跟着数据迁移过来。Navicat的“数据传输”不迁移存储过程、函数、触发器这些PL/SQL对象,它只处理表结构和表数据。这意味着迁移完以后,所有依赖数据库端逻辑的字段(比如自动写入CREATED_DATE、更新LAST_UPDATED_DATE等)都会失效。这个必须提前告知业务方,让他们在应用层补齐逻辑,或者在MySQL里用新语法重建触发器。MySQL的触发器语法跟Oracle差异很大,不能直接复制SQL,需要重写。

三是Oracle的虚拟列和物化视图。虚拟列(Virtual Column)在Navicat的默认映射里可能会被当成普通列迁移,但它的生成表达式是Oracle语法,MySQL不认识,结果就是建表时报错。物化视图就更不用说了,MySQL没有原生物化视图,需要改成普通表+定时刷新的方案。这些都属于迁移范围之外但迁移后必须处理的存量问题,最好在项目计划里单独列出来。

4. 核心实操:Navicat Premium数据迁移全流程

4.1 第一步:配置Oracle与MySQL连接

在Navicat里,“连接”面板分别创建Oracle连接和MySQL连接。

Oracle连接的关键配置项有:

  • 主机:Oracle所在服务器IP
  • 端口:默认1521
  • 服务名或SID:这里最容易弄混。Oracle 11g默认用SID,但很多云数据库对外暴露的是Service Name(服务名)。填错了会报ORA-12514或ORA-12505。建议直接问DBA要tnsnames.ora里的NET_SERVICE_NAME。
  • 连接测试:如果提示找不到OCI库(类似“Cannot load OCI DLL”),就要去Oracle官网下载对应版本的Instant Client,解压后把路径填到Navicat的“OCI library”配置项里。

MySQL连接的配置相对简单:

  • 主机、端口(默认3306)、用户名、密码,填入即可。
  • 连接测试通过后,建议右键连接,打开“编辑连接”,在“高级”标签里确认“使用MySqldump工具”和“使用mysql工具”的路径是否正确。这两个路径用于后续的备份还原,虽然数据传输模式下用不到,但提前配好没坏处。

4.2 第二步:使用“数据传输”工具进行表结构+数据全量迁移

具体操作路径是:在Navicat主界面,选中源Oracle连接下的某个Schema(或者直接右键数据库名),点菜单栏的“工具”→“数据传输”。

在弹出的窗口里,需要做以下设置:

  • :选择要迁移的Oracle数据库(Schema),不要选整个实例,否则会把系统表、系统视图也带进来。

  • 目标:选择之前建好的MySQL数据库。

  • 传输选项

    • “创建表” :勾选,这样会自动建目标表
    • “数据” :勾选,这是数据迁移的主开关
    • “删除目标表”:如果目标表存在且要覆盖,就勾选;如果目标库是空的,可以不勾
    • “使用事务”:建议勾选,这样单个表的数据要么全部写入,要么全部回滚,不会出现半截数据
    • “每次批处理行数”:默认1000,按需调整
  • 对象列表:这里会把源库里的所有表列出来,可以在这一步筛选需要迁移的表,也可以单独调整每个表的目标映射。

点击“开始”后,Navicat会进入传输进度界面,能看到每个表的状态、传输行数、耗时、错误信息。整个过程建议人盯着,至少在头几分钟内确认没有报错再离开。

4.3 第三步:分批迁移大表与续传技巧

一次性把所有表都勾上跑,如果中途有一张表出错,Navicat默认会继续跑后面的表,但出错的那张表不会自动重试。我之前遇到的情况是某张表的CLOB字段里有非法字符,直接中断了整张表,后面的表还是正常跑完了,但那张表始终是0行,很隐蔽。

所以,稳妥的做法是分两批:

  • 第一批:迁移所有小表、配置表,数据量小,执行时间短,适合整体跑一遍发现明显的类型映射问题。
  • 第二批:逐个迁移大表。中途如果一张表跑到一半报错,可以用“筛选条件”功能做续传。

Navicat的数据传输里有一个“高级”选项,可以给源表加WHERE条件。比如一张1.2亿行的表,可以先传主键ID 0到3000万的部分:

WHERE id >= 0 AND id < 30000000

跑完后再把条件改成下一段,这样即使中间失败了,顶多重跑当前段,不用从头再来。这个技巧在数据量巨大、网络不稳定的场景下能救命。

4.4 第四步:使用“Run SQL File”迁移视图和存储过程

Navicat的数据传输不迁移视图(View)、存储过程(Procedure)、函数(Function)、触发器(Trigger)等对象。这部分的迁移方式通常是:

在Oracle连接里,右键数据库 → “转储SQL文件” → “仅结构”,然后把SQL文件用文本编辑器打开,删除Oracle特有语法,改成MySQL语法前缀。改动点包括:

  • CREATE OR REPLACE FORCE VIEW改成CREATE OR REPLACE VIEW
  • 把存储过程里的IS改成AS(MySQL用AS,但其实两种都兼容,关键是参数和变量声明方式)
  • SELECT ... FROM DUAL去掉(MySQL不需要DUAL表,虽然8.0版也支持了但正规写法不写)
  • 把字符串拼接符||改成CONCAT()
  • SYSDATE改成NOW()
  • TO_CHAR(字段, 'YYYY-MM-DD')改成DATE_FORMAT(字段, '%Y-%m-%d')
  • NVL(字段, 0)改成IFNULL(字段, 0)
  • DECODE(a, b, c, d)改成CASE WHEN a = b THEN c ELSE d END

改完之后,在MySQL连接上右键目标数据库,选择“运行SQL文件”,把改好的SQL文件跑一遍,就能把视图和存储过程建出来。这个过程不能省,否则迁移后应用系统一启动就报“找不到视图”或“Procedure不存在”的错误。

注意:存储过程这类代码逻辑的转换,最好找开发同事一起过一遍,因为不只是语法差异,Oracle的PL/SQL和MySQL的存储过程在异常处理、游标、事务控制上都有差异,只做语法翻译容易遗漏业务逻辑。

4.5 第五步:验证数据完整性与统计信息更新

数据迁移完成不等于迁移结束。我习惯做三层校验:

第一层是行数比对。在Oracle查每个表的COUNT(*),在MySQL再查一遍,两张表列出来比对。但这种全表COUNT在大表上很慢,可以用MySQL的information_schema.tables里的TABLE_ROWS和Oracle的NUM_ROWS先粗比,然后对大表抽样精确COUNT。

第二层是抽样内容比对。取每条关键业务表的前100条和最后100条,手工比对几个非索引字段,确认数据内容和顺序没有错位。

第三层是运行MySQL的ANALYZE TABLE,让优化器重新统计表信息:

ANALYZE TABLE user_info;

Oracle端迁移过来的表在MySQL里,统计信息是空的,如果直接跑SQL,执行计划可能完全走偏,该走索引的走了全表扫描。ANALYZE之后执行计划就正常了。

5. 常见问题与排查技巧实录

以下这些坑,都是我实际迁移中踩过的,列出来供参考。

5.1 连接Oracle时提示“Cannot load OCI DLL”

这是Navicat连Oracle最常见的问题。原因就是本机缺少Oracle Client的OCI库,或者Navicat没有找到它。

解决方式:

  • 去Oracle官网下载“Instant Client”对应版本(注意选和Navicat位数一致的,64位Navicat要64位Instant Client,32位同理)。
  • 解压到本地,比如C:\oracle\instantclient_21_12
  • 在Navicat的Oracle连接配置里,下方有一个“OCI library”的输入框,直接浏览选择刚才解压目录下的oci.dll

如果是在Mac上,路径类似,选libclntsh.dylib。设置完成后重新测试连接即可。

5.2 迁移时字段类型报错:Unknown column type

这个报错通常出现在Oracle 12c以后的一些新类型上,比如SYS.XMLTYPESDO_GEOMETRYINTERVAL DAY TO SECOND等。Navicat对新类型的映射不完善,遇到不认识的就直接报错。

解决办法:在“数据传输”的映射界面,手动把这些列的类型改成MySQL支持的等价类型,比如XMLTYPE改成LONGTEXT,SDO_GEOMETRY改成JSON或GEOMETRY(取决于业务是否要用空间计算)。如果源表里这类列数据量大,建议先只迁移结构,再单独写脚本处理数据。

5.3 Oracle的CLOB数据导到MySQL后变截断

大字段截断的问题,通常不是Navicat的限制,而是MySQL侧的max_allowed_packet参数设置太小。MySQL默认值是64M或更小,如果单条INSERT语句里包含了一个超过这个值的CLOB字段内容,导入就会失败。

解决方式:

SET GLOBAL max_allowed_packet = 1073741824; -- 1GB

注意这个参数是动态的,修改后当前会话立即生效,但重启MySQL后会失效。需要在my.cnf的[mysqld]段里也加上对应配置,才能持久化生效。

另外,在Navicat传输大字段表时,建议开启“使用事务”并在“高级”选项里把“每次批处理的行数”降低,避免单条INSERT体积过大。

5.4 主键为空的表迁移后出现重复数据

这个坑不常见,但一旦遇到就很隐蔽。Oracle表本身没有主键,但业务上可能有重复数据。Navicat创建目标表时如果也照搬了无主键结构,那么数据灌入后可能有大量重复行,后续按某字段去重时就会出问题。

我的建议是:无主键表迁移完成后,主动加一个业务无关的自增主键:

ALTER TABLE your_table ADD COLUMN id BIGINT PRIMARY KEY AUTO_INCREMENT FIRST;

有了这个自增主键,后续做数据修复、增量同步、甚至简单的分页查询都更安全。如果担心业务逻辑对列顺序有依赖,可以用AFTER关键字把自增列加到末尾,不改变原有列顺序。

5.5 迁移后MySQL写入慢或大批量更新卡死

数据迁过去之后,如果业务跑起来明显变慢,先别急着说MySQL不如Oracle。检查三件事:

  • 是否执行了ANALYZE TABLE,没有统计信息的表会生成极差的执行计划。
  • 目标表是否没加索引,Oracle里的索引虽然迁过去了,但如果有复合索引、函数索引、位图索引,MySQL并不都支持,尤其是位图索引(MySQL 8.0之前完全没有),这类索引迁移时会直接丢失,需要业务侧重新设计。
  • 大表是否没有分区。在Oracle里做了范围分区的表,到MySQL里如果直接退化成单表,查询性能会显著下降。MySQL 8.0支持RANGE、LIST、HASH、KEY分区,可以按原表的分区键重新设计分区方案,但要注意分区键必须是主键的一部分,这个限制和Oracle不同,设计时要特别注意。

6. 迁移完成后的常见补充操作

数据导完、验证通过,这一步是很多人会掉的坑:以为迁移完了就直接给业务方交接,结果业务一上线就各种报错。补充操作主要有以下几个。

补充操作一,是更新MySQL的AUTO_INCREMENT。如果你在迁移前修改了表结构加了自增主键,或者源表用了Oracle的序列,那么一定要把MySQL的AUTO_INCREMENT设置成源表最大ID+1,否则新插入的数据会主键冲突。这个前面提到了,再强调一次,因为实际工作中这个隐患不报错,直到业务写入才爆。

补充操作二,是核对MySQL的字符集排序规则。Oracle数据库里的中文排序规则和MySQL的utf8mb4_unicode_ci排序结果不完全一样,如果业务依赖ORDER BY中文排序,迁移后可能看起来怪怪的。建议在测试阶段专门跑一遍中文排序的SQL,确认排序结果是否可接受。

补充操作三,是检查时区设置。Oracle的SYSTIMESTAMP和MySQL的CURRENT_TIMESTAMP对时区的处理逻辑不同。MySQL的time_zone默认是SYSTEM,如果目标服务器时区和业务时区不一致,NOW()返回的时间可能对不上。建议在连接参数或MySQL配置文件里明确设置时区,比如:

SET GLOBAL time_zone = '+08:00';

转移过程中如果涉及TIMESTAMP WITH TIME ZONE类型的字段,尤其要关注这一点。

补充操作四,是索引碎片整理。大批量INSERT进来的数据,InnoDB的B+树索引很容易产生碎片,跑一段时间后写入性能会下降。建议在迁移完成后跑一次OPTIMIZE TABLE(等价于重建表)来整理碎片。注意这个操作会锁表,要在业务低峰期做。

7. 迁移性能优化:让数据传输跑得更快

Navicat的默认传输参数偏保守,实际使用时可以针对大表做几项调整,明显提升迁移速度。

一是调整批处理行数。默认的1000行每批,对OLTP小表没问题,但对大表来说太小了,INSERT的执行频率太高,网络往返次数也多。我实测中把批处理行数调到5000,传输速度能提升30%到50%。如果目标表字段多、单行体积大,批处理行数调大后单条INSERT的体积也会增大,要确保max_allowed_packet足够。

二是关闭“每次传输前删除目标表数据”的选项。如果你已经确定目标表是干净的,没必要在传输前再删一次。这个选项开着,Navicat会先执行DELETE FROM或者DROP TABLE再重建,多一步操作,大表上特别浪费时间。

三是调整MySQL的写入相关参数。比如innodb_flush_log_at_trx_commit = 2(或0),sync_binlog = 0,能显著降低磁盘写入频率,加快大批量导入。但注意这些是牺牲可靠性换速度的临时参数,迁移结束后一定要改回来。我个人建议如果迁移窗口允许,直接用默认参数慢慢导,毕竟数据一致性比速度快更重要。

四是用多线程方案。Navicat的“数据传输”默认是单线程,也就是同一时刻只处理一张表。如果你的源库表很多,且都是小表,单线程的效率确实不高。Navicat Premium 17版本部分场景支持并行传输,但实测下来不是所有版本都开放。实在需要并行时,可以多开几个Navicat窗口,分别迁移不同批次的表,物理并行。这么做的前提是目标MySQL的写入性能和磁盘IO扛得住并发,否则反而会拖慢整体速度。

8. 迁移质量核验清单

最后提供一份自用迁移质量核验清单,每次迁移完都照着过一遍:

核验项具体操作通过标准
表数量一致性源库和目标库查询表数量完全一致
行数一致性关键表逐表COUNT(*)比对大表抽样,小表全量
字段类型正确性抽查目标表所有字段类型与精度Number→Decimal位数为8位以上的需单独核对
大字段数据完整性对CLOB/TEXT字段抽样比对长度和首尾字符无截断,长度一致
字符集与乱码抽查中文字段值和emoji字符显示正常,无乱码
主键自增起始值查询AUTO_INCREMENT值大于源表最大ID
索引与约束比对源库和目标库索引数量关键业务索引不缺失
存储过程与视图运行编译检查无语法错误
时间字段抽样比对yyyy-MM-dd HH:mm:ss格式时分秒不丢失
统计信息执行ANALYZE TABLE完成
业务联调让业务方跑一轮核心冒烟用例通过

这套清单看起来繁琐,但实际执行下来也就半天时间。相比迁移后线上出问题再排查,这点时间花得非常值。

我自己做了这么多次迁移,最大的体感是:Navicat这个工具解决的是“把数据搬过去”的问题,但真正决定迁移成败的是“搬之前怎么想”和“搬完之后做什么”。数据类型映射、自增主键、统计信息、字符集这些细节,任何一个没处理到位,都可能让后续的业务运行埋下隐患。希望这篇内容能帮到正打算动Oracle到MySQL迁移的朋友,少走几步弯路。

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

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

立即咨询