記一次簡單的Oracle離線資料遷移至TiDB過程

balahoho發表於2022-01-19

背景

最近在支援一個從Oracle轉TiDB的專案,為方便應用端相容性測試需要把Oracle測試環境的庫表結構和資料同步到TiDB中,由於資料量並不大,所以怎麼方便怎麼來,這裡使用CSV匯出匯入的方式來實現。

整個過程可以分為三個步驟:

  • 庫表結構轉換
  • 源資料匯出
  • 匯入目標庫

庫表結構轉換

眾所周知TiDB是相容MySQL協議的,所以Oracle的表結構定義在TIDB不一定能完全使用,這時候就需要做一些轉換,比如欄位型別、關鍵字、系統函式等等。如果表比較少的話,手動轉一下也不是不行,但本次測試的Oracle其中一個使用者下就有將近900張表,手動去轉換顯然不可能。

這裡我使用的工具是TransferDB,它可以支援異構資料Oracle到MySQL/TiDB的結構轉換,專案主頁https://github.com/wentaojin/transferdb

這個工具由PingCAP某位大佬開發,雖然沒有正式對外發布,但確實挺好用的。TransferDB是TiDB運維常用工具集(TiDBA)中的一部分,其他的還包含收集統計資訊、Mok 解析 key、基於 region key、資料 range、資料估算生成打散語句、檢視錶資料以及索引 region leader 分佈、版本升級,比對 3.0 以及 4.0 配置檔案以及 tidb 系統變數等,可以說是非常實用了,它的專案主頁是https://github.com/wentaojin/tidba

使用過Lightning的朋友對這個工具的使用一定不會陌生,從配置檔案到執行程式幾乎可以說是如出一轍,專案自帶的操作手冊也寫的非常詳細。

它包含以下幾點核心功能:schema轉換、表結構檢查、遷移成本評估、資料遷移(全量或增量)、CSV匯出等,其中有些功能目前還是實驗特性,我這裡只用到了它的核心特性schema轉換。

它的配置檔案引數非常豐富,註釋很清晰使用起來非常簡單,對於schema轉換場景來說,只需要修改[source][target]部分的連線資訊就行,詳細的配置清單可以看這裡:https://github.com/wentaojin/transferdb/blob/main/conf/config.toml

配置檔案修改好以後,執行下面兩條命令就可以實現轉換:

# 這個過程是在目標庫中生成一個遷移元資訊庫,用來儲存轉換規則、斷點資訊等等,類似於DM中的dm_meta庫
./transferdb --config config.toml --mode prepare  
# 這個過程是實現schema轉換,輸出sql檔案
./transferdb --config config.toml --mode reverse

執行成以後會生成2個SQL檔案,一個叫 reverse_${sourcedb}.sql,它是在TiDB中可以執行的sql,另一個是 compatibility_${sourcedb}.sql,它是TiDB不相容的sql,比如Foreign Key、Constraint等等,這部分SQL需要人工去評估下使用別的方案來實現。

接著,把reverse_${sourcedb}.sql匯入到TiDB即可,常用的兩種方式:

  • mysql -h -u -P < reverse.sql
  • source reverse.sql

源資料匯出

Oracle資料匯出到CSV檔案我使用sqluldr2來實現,這是一款在Oracle使用非常廣泛的資料匯出工具,它的特點就是小巧、輕便、速度快、跨平臺、支援自定義SQL。

網上的資料比較多,這裡就不詳細介紹怎麼去使用了,作者(前阿里資料庫大佬)也寫了一份超級詳細的文件,大家搜尋sqluldr2超詳細使用教程-loracle資料匯出工具及方法即可。

sqluldr2雖然很強大,但它卻不支援批量匯出這點很讓人迷惑,沒辦法只能另闢蹊徑來實現了。

我先把需要匯出的表清單放到一個txt檔案中:

./sqluldr2linux64.bin user=user/pwd@192.168.1.1:1521/orcl query='select table_name from all_tables where owner='test';' file=/tmp/tidb/sqluldr_tables.sql

再寫一個批處理指令碼把所有表進行匯出:

#!/bin/bash

cat /tmp/tidb/sqluldr_tables.sql | while read line
do
    echo $line
    /tmp/tidb/sqluldr2linux64.bin user=user/pwd@192.168.1.1:1521/orcl query={$line} charset=UTF8 field=0x7c0x260x7c record=0x3d0x37 null=null file=/tmp/tidb/data/orcltest.{$line}.csv
done

這裡有幾點需要注意:

  • 欄位分隔符和換行符建議使用複雜的字元,最好使用多種組合字元(推薦使用ASCII碼),這樣能儘可能的避免出現匯出的資料value count和column count不一致的情況。
  • 匯出的檔案字符集設定成UTF8格式,避免資料匯入到TiDB後出現中文亂碼
  • 由於後面要使用Lightning匯入CSV,檔案命名格式要符合Lightning的要求,即{dbname}.{tablename}.csv

到這裡資料就準備就緒了。

匯入到TiDB

往TiDB中匯入CSV檔案有兩種常用的方式,第一種就是Lightning,第二種是Load Data,無論是從操作上還是效能上我都推薦優先考慮Lightning,原因如下:

  • Load Data只能匯入單個檔案,Lightning可以批量匯入
  • Lightning以效能著稱,支援多種後端模式,Load Data只能走計算層,還有記憶體放大現象
  • 對於異常情況,Lightning可以斷點續傳,Load Data要清理資料重新匯入

單從900個csv檔案來看,Lightning絕對是第一選擇。

這裡貼一下Lightning的幾項核心配置:

[tikv-importer]
# 選擇使用的 local 後端
backend = "local"
# 設定排序的鍵值對的臨時存放地址,目標路徑需要是一個空目錄
sorted-kv-dir = "/tmp/tidb/lightning_dir"

[mydumper]
data-source-dir = "/tmp/tidb/data"
no-schema = true
filter = ['*.*']

[mydumper.csv]
# 欄位分隔符,支援一個或多個字元,預設值為 ','。
separator = '|&|'
# 引用定界符,設定為空表示字串未加引號。
delimiter = ''
# 行尾定界字元,支援一個或多個字元。設定為空(預設值)表示 "\n"(換行)和 "\r\n" (回車+換行),均表示行尾。
terminator = "=%"
# CSV 檔案是否包含表頭。
# 如果 header = true,將跳過首行。
header = false
# CSV 檔案是否包含 NULL。
# 如果 not-null = true,CSV 所有列都不能解析為 NULL。
not-null = false
# 如果 not-null = false(即 CSV 可以包含 NULL),
# 為以下值的欄位將會被解析為 NULL。
null = '\N'
# 是否對欄位內“\“進行轉義
backslash-escape = true
# 如果有行以分隔符結尾,刪除尾部分隔符。
trim-last-separator = false

注意事項:
- 推薦使用local模式,這樣應對blob型別的資料處理更友好
- 不需要匯入表結構,所以設定no-schema = true
- 分隔符和換行符這些要和sqluldr2設定的一樣

最後執行Lightning即可:

./tidb-lightning --config tidb.toml --checkrequirements=false

這個過程中我還發現了一個Lightning的bug,後面我會嘗試自己修復一下。

其他部分

至於Oracle的其他部分例如儲存過程和自定義函式,也不用多想怎麼去遷移了,老老實實改程式碼去應用端實現。

檢視的話我是先用PLSQL把檢視導成sql檔案再匯入TiDB中,但是報錯的比較多,基本都是系統函式和語法不相容問題,這部分就涉及SQL改寫了,沒有什麼好的辦法。

總結

在之前的專案中也使用過DSG來實現Oracle到TiDB的資料遷移,但它畢竟是個純商業性工具,先充錢才能玩,對於這種測試階段來說不是太好的選擇。
當然了,官方釋出的《TiDB in Action》一書中也給出了Oracle到TiDB的遷移案例:https://book.tidb.io/session4/chapter5/from-oracle-to-tidb.html,它基於Oracle自家的OGG元件來實現,部署使用上稍微有點麻煩。

本文提到的幾個工具都是隨取隨用,不需要安裝各種依賴環境,這對於我現在面對的這種沒有網路沒有yum源的伺服器來說簡直太舒服了,在這樣的小資料量測試場景中不失是一種選擇。

更多好方案也歡迎大家推薦,為TiDB生態助力。

相關文章