【環境部署】使用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的正確性,都是業務性功能,這裏不作詳細介紹。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章