數據訪問代理(Open Database Proxy,簡稱 ODP)通過集成 DataX,支持全量離線靜態的數據遷移功能。DataX 是阿里巴巴集團內被廣泛使用的離線數據同步工具/平臺,實現各種異構數據源之間高效的數據同步。目前,支持的源端數據源類型依賴于 DataX 支持的類型,而目標端僅支持 MySQL 和 OceanBase。
本文將引導您快速完成以下遷移任務:
單庫單表 MySQL 遷移至 ODP
前置條件
您已經開通數據訪問代理產品并購買了數據訪問代理實例,詳見 創建實例。
建庫建表
登錄數據訪問代理控制臺頁面,選擇 數據庫,單擊 創建數據庫。
在彈出的 創建數據庫 窗口中,選擇實例,單擊 創建。
進入 選擇數據節點 頁面后,根據需要選擇 MySQL 或 OceanBase 的節點,單擊 下一步。
根據提示,填寫或選擇數據庫的基本信息。詳細參數信息,請參見 創建數據訪問代理數據庫。
數據庫創建完成后,進入數據庫詳情頁,單擊右側頁面下方的 新增數據表。
在 新增數據表 頁面,輸入 數據表名,如
test_migration_user
。根據需要選擇表類型(單表或拆分表),此處以 拆分表 為例,并設置 分表總數 為 2。
配置分表規則,詳細配置方法可參見 創建數據訪問代理數據表 和 自定義分表規則。
勾選 現在創建物理表,單擊 下一步。
在 DDL 語句 中,輸入建表語句,示例如下:
CREATE TABLE `test_migration_user`( `user_id` varchar(16) NOT NULL, `username` varchar(64) NOT NULL, `id` bigint(20) NOT NULL AUTO_INCREMENT, PRIMARY KEY (`id`), UNIQUE KEY `uk_user_id`(`user_id`) ) ENGINE=InnoDB AUTO_INCREMENT=102 DEFAULT CHARSET=utf8mb4;
單擊 執行,完成建表。
創建遷移賬戶
在數據訪問控制臺頁面,左側導航欄選擇 實例。
在實例列表中,找到剛剛創建的數據庫所在的實例,單擊實例名稱,進入實例詳情頁。
切換至 賬號管理 頁簽,單擊 創建賬號。
在彈出的新窗口中,輸入數據庫賬號(必須是 odp_migrator)和賬號密碼,選擇相應的授權數據庫。
單擊 確定,完成創建遷移賬戶。
配置連接參數
進入數據庫詳情頁,選擇頁面下方的 連接參數 頁簽。
切換至 其他參數 后,在 connectionProperties 屬性欄,輸入以下屬性值:
rewriteBatchedStatements=true clobberStreamingResults=true
單擊底部 保存配置 按鈕。
準備 DataX 環境
DataX 是一個異構數據源間數據遷移的中間件,支持各種類型的 reader 和 writer。要實現 ODP 數據遷移,您需要準備 DataX 環境。
單擊此處 下載 DataX,并將其解壓至本地目錄。
單擊此處 下載 odpwriter 插件,并將其解壓至
$datax_dir/plugin/writer
目錄下。
有關 DataX 的更多信息,參見 DataX 官方文檔。
編輯并執行遷移 Job
進入
$datax_dir/bin
目錄,編寫一份遷移 Job 描述文件。文件示例如下:{ "job": { "setting": { "speed": { "channel": 3 }, "errorLimit": { "record": 0, "percentage": 0.02 } }, "content": [ { "reader": { "name": "mysqlreader", "parameter": { "username": "$mysql_usr", "password": "$mysql_pwd", "column": [ "user_id", "username" ], "splitPk": "id", "connection": [ { "table": [ "user" ], "jdbcUrl": [ "jdbc:mysql://127.0.0.1:3306/test_migration" ] } ] } }, "writer": { "name": "odpwriter", "parameter": { "writeMode": "replace", "username": "odp_migrator", "password": "$odp_pwd", "column": [ "user_id", "username" ], "connection": [ { "jdbcUrl": "jdbc:mysql://$dbp_url/test_migration?useUnicode=true&characterEncoding=utf8", "table": [ "test_migration_user" ] } ] } } } ] } }
根據以上 Job 描述文件,該數據遷移任務是將單庫單表的 MySQL(
127.0.0.1:3306
)中的test_migration
庫里的user
表的數據(列user_id
,username
)遷移至$dbp_url
中的test_migration
庫里的test_migration_user
表(列user_id
,username
)。在
$datax_dir/bin
目錄下,執行以下命令,運行數據遷移 Job:python datax.py $yourjob.json
命令執行成功,即數據遷移完成。
ODP 遷移至其他數據庫
從 ODP 遷移至其他數據庫,操作步驟與 從 MySQL 遷移至 ODP 相似。
準備 DataX 環境
單擊此處 下載 DataX,并將其解壓至本地目錄。
單擊此處 下載 odpreader 插件,并將其解壓至
$datax_dir/plugin/reader/
目錄下。
執行 Job 描述文件
進入
$datax_dir/bin
目錄,編寫一份遷移 Job 描述文件。文件示例如下:說明Reader 遷移賬號也必須是 odp_migrator。
對 Job 描述文件添加一個 connection 的校驗,僅允許配置一個 connection,且僅允許配置一張表。
{ "job": { "setting": { "speed": { "channel": 4 }, "errorLimit": { "record": 0, "percentage": 0.02 } }, "content": [ { "reader": { "name": "odpreader", "parameter": { "username": "odp_migrator", "password": "$odp_pwd", "column": [ "user_id", "gmt_create", "gmt_modified", "current_date", "current_time", "current_timestamp", "name", "is_ok", "age", "salary", "height", "memo", "character_stream", "binary_stream", ], "connection": [ { "table": [ "test_migration_user_large" ], "jdbcUrl": [ "jdbc:mysql://$odp_url:8066/test_join?useUnicode=true&characterEncoding=utf8" ] } ] } }, "writer": { "name": "odpwriter", "parameter": { "writeMode": "replace", "username": "odp_migrator", "password": "$odp_pwd", "column": [ "`user_id`", "`gmt_create`", "`gmt_modified`", "`current_date`", "`current_time`", "`current_timestamp`", "`name`", "`is_ok`", "`age`", "`salary`", "`height`", "`memo`", "`character_stream`", "`binary_stream`", ], "batchSize": 2048, "connection": [ { "jdbcUrl": "jdbc:mysql://$odp_url:8066/test_join?useUnicode=true&characterEncoding=utf8", "table": [ "test_migration_user_large_target" ] } ] } } } ] } }
在
$datax_dir/bin
目錄下,執行如下命令,運行數據遷移 Job。python datax.py $yourjob.json
命令執行成功,即數據遷移完成。
注意事項
不推薦使用 SCAN_ALL
hint + mysql reader 的方式進行數據讀取。雖然這種方式也可以對分庫分表的數據表進行數據抽取。但其數據拆分方式為 splitPK
,即全表掃描之后,根據 ID 進行拆分,拆分之后的每個子任務 $from ~ $to 同樣需要全表掃描才能取出。這就意味著,任務拆分之后,每個子任務的查詢都是一次全表掃描。因此,這種方式性能差、容易超時,而且會對數據訪問代理實例產生較大的負載壓力,不建議使用。
相比之下,odpreader 的拆分方式是基于邏輯表的分表來實現的,如百庫百表下會拆分為 100 個子任務,每個子任務的數據抽取僅會查詢單個分表,并不會產生全表掃描。因此,建議您使用 odpreader。
常見問題
DataX 支持的數據類型
DataX 的 MysqlReader 針對 MySQL 類型轉換列表如下:
DataX 內部類型 | MySQL 數據類型 |
---|---|
long | int, tinyint, smallint, mediumint, int, bigint |
Double | float, double, decimal |
String | varchar, char, tinytext, text, mediumtext, longtext, year |
Date | date, datetime, timestamp, time |
Boolean | bit, bool |
Bytes | tinyblob, mediumblob, blob, longblob, varbinary |
除上述字段類型外,其他類型均不支持。
對于
tinyint(1)
,DataX 視為整型。對于
year
,DataX 視為字符串類型。對于
bit
,DataX 視為未定義行為。
事務與出錯重跑
在數據遷移過程中,可能存在部分數據寫入失敗的情況,此時需要進行重試。由于此時可能已經有部分數據已經完成遷移,重試的時候回出現 Duplicate Key 問題。此時,可以使用 DataX 的 REPLACE/INSERT IGNORE writeMode。
需要注意,REPLACE 語句的行為是如果發現主鍵或唯一鍵沖突,會將原來這條數據刪除,然后重新插入,這樣既可實現比較簡單的出錯重跑機制。REPLACE 語句可能會導致新的數據記錄的自增 id 有變化,如果使用自增 id 進行關聯,會出現問題。而 INSERT IGNORE 語句則不會有這個問題,如果發現主鍵或唯一鍵沖突,會忽略當前這條 SQL 的插入。
超時問題
SocketTimeout 錯誤
現象:
出現 SocketTimeout 報錯,類似的錯誤信息如下所示:
Thelast packet successfully received from the server was 5,004 milliseconds ago.Thelast packet sent successfully to the server was 5,004 milliseconds ago.
解決方案:
登錄數據訪問代理控制臺,進行目標數據庫的詳情頁。
選擇頁面下方的 連接參數 頁簽,在 其他參數 > connectionProperties 屬性欄,添加如下屬性:
socketTimeout=5000(調整為更大的數值,默認為5秒,單位為毫秒)
單擊 保存配置。
Timeout 錯誤
現象:
出現 Timeout 報錯,對應的錯誤碼為 4012。
原因:
該錯誤是 OceanBase 查詢超時問題。
解決方案:
您可以通過以下方法處理該錯誤:
在任意一個 column 中加入 hint:
/*+空格QUERY_TIMEOUT(111111111)空格*/ $columnName
,示例如下:"column":[ "/*+ QUERY_TIMEOUT(100) */ user_id", "username", "id", "gmt_create", ],
說明該超時時間僅影響當前SQL,并不會影響其他SQL。
在 newConnectionSql 中添加
ob_query_timeout
參數,單位為微秒。set@@ob_query_timeout=比較大的值
說明該參數配置將影響整個邏輯庫。在離線與在線業務混用 ODP 實例的場景中,不推薦使用這種參數配置。可以在直連物理庫時執行這條 SQL,檢查該超時參數設置為多大值時不會超時,然后在此基礎上再加一些 buffer。
Communications link failure 錯誤
現象:
出現 Communications link failure 報錯,錯誤信息如下所示:
Communications link failure
Thelast packet successfully received from the server was 0 milliseconds ago.Thelast packet sent successfully to the server was 605,920 milliseconds ago.
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException:Communications link failure
Causedby: java.io.EOFException:Cannot read response from server.Expected to read 425 bytes, read 156 bytes before connection was unexpectedly lost.
原因:
該錯誤是因為數據庫達到了 net_write_timeout
而主動斷連導致的,即數據庫回寫超時。
解決方案:
數據遷移(流式讀取)時默認值為 600 秒,您可以通過設置以下 ODP 連接參數,解決該問題。
netTimeoutForStreamingResults=大于600的一個數值,單位是秒