【环境部署】使用Navicat DB将数据从Oracle迁移到MySQL

0. 概述

最近一个项目在实施过程中需要将原有的Oracle数据库变更为开源的MySQL数据库。迁移宗旨:迁移过程尽量减少修改对应工作量,不能影响业务功能。通过调查分析,本次迁移主要涉及以下两方面工作:

  • 数据库本身迁移
  • Java持久化业务SQL迁移

1. 数据库迁移

1.1. Navicat迁移数据表

Navicat Premium比较强大,能够连接大部分主流关系型数据库,操作方便、界面简洁,同时可以跨库批量迁移数据表。
在这里插入图片描述

​ (1)新建要迁移的Oracle数据库的连接
在这里插入图片描述

​ (2)新建迁移目标MySQL库的连接
在这里插入图片描述

(3) 选择【工具】→【数据传输】
在这里插入图片描述

  • 左侧为数据源Oracle的信息,选择刚才创建的Oracle数据库的连接名。模式,请选择在该数据库实例中的用户。
  • 右侧为数据目标MySQL的信息,选择刚才创建的MySQL数据库的连接名,数据库为创建的需要导入的数据库。
  • 从Oracle只能迁移表对象到MySQL,Oracle的其他对象:视图、过程、函数、序列等需要单独处理。
  • 顺利的话,数据库表能够顺利迁移,我们业务表迁移过程中遇到如下两个问题。

1.2. Navicat迁移问题及对策

1.2.1. Navicat 连接Oracle报错:ORA-28547

问题现象

Navicat安装时默认包含一个某个版本OCI文件,如果OCI文件的版本和服务器端Oracle的版本不匹配,将会导致ORA-28547问题的产生。
在这里插入图片描述

解决方法

下载对应服务器版本的instant-client,并替换Navicat中使用的OCI文件。下载网址:【OCI文件】

Navicat中设定OCI文件如下图:(【工具】→【选项】)
在这里插入图片描述

1.2.2 日期类型迁移出错

问题描述

MySQL和Oracle数据库中,日期类型不同,Oracle中的DATE(精度为7位)大于MySQL中的最大精度6位。所以该字段迁移出现如下问题。
在这里插入图片描述

解决方法

使用PL/SQLDeveloper将Oracle数据库的脚本导出,使用编辑器修批量替换数据库脚本中的DATE数据类型为:TIMESTAMP(0),具体精度根据自己的业务自行设定。
在这里插入图片描述

重新建立一个新的数据库实例,将修改后的DB脚本执行后创建一个Oracle原始库的副本。然后重新使用Navicat再次进行数据迁移。

数据导入:需要进行一下简单的修改,Oracle直接导出SQL插入数据脚本参考下图中红色边框标记部分,为了能够修改成在MySQL中直接执行的语句,请按照蓝色背景部分的格式进行替换。
在这里插入图片描述
在这里插入图片描述

  • 函数替换:(Oracle)to_date → (MySQL)str_to_date
  • 格式化匹配串替换:(Oracle)‘dd-mm-yyyy hh24:mi:ss’→ (MySQL)’%d-%m-%Y %H:%i:%s’

1.2.3 索引字符类型出错

问题描述

数据类型是TEXT/BLOB类型,并作为MySQL中的主键的时候,如果该类型缺少明确的长度值,MySQL无法保证主键的唯一性,导致该问题产生。

[Err][Dtf] 1170 - BLOB/TEXT column 'AUTHORITY_CODE' used in key specification without a key length

解决方法

当使用 TEXT/BLOB类型的数据作为索引的时候,需要明确数据的长度。MySQL中VARCHAR默认长度是255个字符,所以需要判断业务数据的大小,如果Oracle中的业务数据能够在255个字符之内,则需要将Oracle中字段(VARCHAR2)的长度修改在255以内。或者暂时将该字段从索引主键中删除。本项目按照调整字段长度的方式进行迁移。使用PL/SQLDeveloper将相应问题字段长度调整为255,再次使用Navicat进行数据迁移。

1.3 视图、序列迁移

1.3.1 视图迁移(Oracle→MySQL)

本次项目中就一个简单视图,直接使用PL/SQLDeveloper导出视图脚本后可以直接在Navicat中执行创建相应的视图。如果存在函数差异的话,单独针对具体的字段和具体函数进行处理。

1.3.2 序列迁移

Oracle使用序列(Sequence)和业务前缀来处理主键字段,迁移到MySQL时,其自增长(increment)不能完全实现原来的Sequence的功能,因此,使用函数的方式来模拟Oracle序列的方案。

  • 创建Sequence表,用来存储序列名称和值
  • 创建currval和nextval用来取值
-- ----------------------------
-- Table structure for sequence
-- ----------------------------
DROP TABLE IF EXISTS `sequence`;
CREATE TABLE `sequence` (
  `seqName` varchar(50) NOT NULL DEFAULT '' COMMENT '序列名',
  `currentVal` int(11) NOT NULL COMMENT '当前值',
  `incrementVal` int(11) NOT NULL DEFAULT '1' COMMENT '自增值',
  PRIMARY KEY (`seqName`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE FUNCTION `currval`(vSeqName VARCHAR(50)) RETURNS int(11)
begin
    declare value integer;
    set value = 0;
    select currentVal into value from sequence
	       where seqName = vSeqName;
    return value;
end
CREATE FUNCTION `nextval`(vSeqName VARCHAR(50)) RETURNS int(11)
begin
    update sequence set currentVal = currentVal + incrementVal where seqName = vSeqName;
    return currval(vSeqName);
end

在这里插入图片描述

2. Java持久化业务SQL迁移

本项目使用MyBatis进行数据库的访问,所以重点在XML文件的迁移上。为此单独做了一个测试XML正确性的Demo,方便单独验证每个SQL的正确性,都是业务性功能,这里不作详细介绍。

发布了24 篇原创文章 · 获赞 12 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/gavinbj/article/details/104085833
今日推荐