MysqlReader 插件文檔
1 快速介紹
MysqlReader插件實現了從Mysql讀取數據。在底層實現上,MysqlReader通過JDBC連接遠程Mysql數據庫,並執行相應的sql語句將數據從mysql庫中SELECT出來。
不同於其他關系型數據庫,MysqlReader不支持FetchSize.
2 實現原理
簡而言之,MysqlReader通過JDBC連接器連接到遠程的Mysql數據庫,並根據用戶配置的信息生成查詢SELECT SQL語句,然后發送到遠程Mysql數據庫,並將該SQL執行返回結果使用DataX自定義的數據類型拼裝為抽象的數據集,並傳遞給下游Writer處理。
對於用戶配置Table、Column、Where的信息,MysqlReader將其拼接為SQL語句發送到Mysql數據庫;對於用戶配置querySql信息,MysqlReader直接將其發送到Mysql數據庫。
3 功能說明
3.1 配置樣例
- 配置一個從Mysql數據庫同步抽取數據到本地的作業:
{
"job": {
"setting": {
"speed": {
"channel": 3
},
"errorLimit": {
"record": 0,
"percentage": 0.02
}
},
"content": [
{
"reader": {
"name": "mysqlreader",
"parameter": {
"username": "root",
"password": "root",
"column": [
"id",
"name"
],
"splitPk": "db_id",
"connection": [
{
"table": [
"table"
],
"jdbcUrl": [
"jdbc:mysql://127.0.0.1:3306/database"
]
}
]
}
},
"writer": {
"name": "streamwriter",
"parameter": {
"print":true
}
}
}
]
}
}
- 配置一個自定義SQL的數據庫同步任務到本地內容的作業:
{
"job": {
"setting": {
"speed": {
"channel":1
}
},
"content": [
{
"reader": {
"name": "mysqlreader",
"parameter": {
"username": "root",
"password": "root",
"connection": [
{
"querySql": [
"select db_id,on_line_flag from db_info where db_id < 10;"
],
"jdbcUrl": [
"jdbc:mysql://bad_ip:3306/database",
"jdbc:mysql://127.0.0.1:bad_port/database",
"jdbc:mysql://127.0.0.1:3306/database"
]
}
]
}
},
"writer": {
"name": "streamwriter",
"parameter": {
"print": false,
"encoding": "UTF-8"
}
}
}
]
}
}
3.2 參數說明
-
jdbcUrl
-
描述:描述的是到對端數據庫的JDBC連接信息,使用JSON的數組描述,並支持一個庫填寫多個連接地址。之所以使用JSON數組描述連接信息,是因為阿里集團內部支持多個IP探測,如果配置了多個,MysqlReader可以依次探測ip的可連接性,直到選擇一個合法的IP。如果全部連接失敗,MysqlReader報錯。 注意,jdbcUrl必須包含在connection配置單元中。對於阿里集團外部使用情況,JSON數組填寫一個JDBC連接即可。
jdbcUrl按照Mysql官方規范,並可以填寫連接附件控制信息。具體請參看Mysql官方文檔。
-
必選:是
-
默認值:無
-
-
username
-
描述:數據源的用戶名
-
必選:是
-
默認值:無
-
-
password
-
描述:數據源指定用戶名的密碼
-
必選:是
-
默認值:無
-
-
table
-
描述:所選取的需要同步的表。使用JSON的數組描述,因此支持多張表同時抽取。當配置為多張表時,用戶自己需保證多張表是同一schema結構,MysqlReader不予檢查表是否同一邏輯表。注意,table必須包含在connection配置單元中。
-
必選:是
-
默認值:無
-
-
column
-
描述:所配置的表中需要同步的列名集合,使用JSON的數組描述字段信息。用戶使用*代表默認使用所有列配置,例如['*']。
支持列裁剪,即列可以挑選部分列進行導出。
支持列換序,即列可以不按照表schema信息進行導出。
支持常量配置,用戶需要按照Mysql SQL語法格式: ["id", "`table`", "1", "'bazhen.csy'", "null", "to_char(a + 1)", "2.3" , "true"] id為普通列名,`table`為包含保留在的列名,1為整形數字常量,'bazhen.csy'為字符串常量,null為空指針,to_char(a + 1)為表達式,2.3為浮點數,true為布爾值。
-
必選:是
-
默認值:無
-
-
splitPk
-
描述:MysqlReader進行數據抽取時,如果指定splitPk,表示用戶希望使用splitPk代表的字段進行數據分片,DataX因此會啟動並發任務進行數據同步,這樣可以大大提供數據同步的效能。
推薦splitPk用戶使用表主鍵,因為表主鍵通常情況下比較均勻,因此切分出來的分片也不容易出現數據熱點。
目前splitPk僅支持整形數據切分,
不支持浮點、字符串、日期等其他類型
。如果用戶指定其他非支持類型,MysqlReader將報錯!如果splitPk不填寫,包括不提供splitPk或者splitPk值為空,DataX視作使用單通道同步該表數據。
-
必選:否
-
默認值:空
-
-
where
-
描述:篩選條件,MysqlReader根據指定的column、table、where條件拼接SQL,並根據這個SQL進行數據抽取。在實際業務場景中,往往會選擇當天的數據進行同步,可以將where條件指定為gmt_create > $bizdate 。注意:不可以將where條件指定為limit 10,limit不是SQL的合法where子句。
where條件可以有效地進行業務增量同步。如果不填寫where語句,包括不提供where的key或者value,DataX均視作同步全量數據。
-
必選:否
-
默認值:無
-
-
querySql
- 描述:在有些業務場景下,where這一配置項不足以描述所篩選的條件,用戶可以通過該配置型來自定義篩選SQL。當用戶配置了這一項之后,DataX系統就會忽略table,column這些配置型,直接使用這個配置項的內容對數據進行篩選,例如需要進行多表join后同步數據,使用select a,b from table_a join table_b on table_a.id = table_b.id
當用戶配置querySql時,MysqlReader直接忽略table、column、where條件的配置
,querySql優先級大於table、column、where選項。-
必選:否
-
默認值:無
3.3 類型轉換
目前MysqlReader支持大部分Mysql類型,但也存在部分個別類型沒有支持的情況,請注意檢查你的類型。
下面列出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屬於未定義行為
。
4 性能報告
4.1 環境准備
4.1.1 數據特征
建表語句:
CREATE TABLE `tc_biz_vertical_test_0000` (
`biz_order_id` bigint(20) NOT NULL COMMENT 'id',
`key_value` varchar(4000) NOT NULL COMMENT 'Key-value的內容',
`gmt_create` datetime NOT NULL COMMENT '創建時間',
`gmt_modified` datetime NOT NULL COMMENT '修改時間',
`attribute_cc` int(11) DEFAULT NULL COMMENT '防止並發修改的標志',
`value_type` int(11) NOT NULL DEFAULT '0' COMMENT '類型',
`buyer_id` bigint(20) DEFAULT NULL COMMENT 'buyerid',
`seller_id` bigint(20) DEFAULT NULL COMMENT 'seller_id',
PRIMARY KEY (`biz_order_id`,`value_type`),
KEY `idx_biz_vertical_gmtmodified` (`gmt_modified`)
) ENGINE=InnoDB DEFAULT CHARSET=gbk COMMENT='tc_biz_vertical'
單行記錄類似於:
biz_order_id: 888888888
key_value: ;orderIds:20148888888,2014888888813800;
gmt_create: 2011-09-24 11:07:20
gmt_modified: 2011-10-24 17:56:34
attribute_cc: 1
value_type: 3
buyer_id: 8888888
seller_id: 1
4.1.2 機器參數
-
執行DataX的機器參數為:
- cpu: 24核 Intel(R) Xeon(R) CPU E5-2630 0 @ 2.30GHz
- mem: 48GB
- net: 千兆雙網卡
- disc: DataX 數據不落磁盤,不統計此項
-
Mysql數據庫機器參數為:
- cpu: 32核 Intel(R) Xeon(R) CPU E5-2650 v2 @ 2.60GHz
- mem: 256GB
- net: 千兆雙網卡
- disc: BTWL419303E2800RGN INTEL SSDSC2BB800G4 D2010370
4.1.3 DataX jvm 參數
-Xms1024m -Xmx1024m -XX:+HeapDumpOnOutOfMemoryError
4.2 測試報告
4.2.1 單表測試報告
通道數 | 是否按照主鍵切分 | DataX速度(Rec/s) | DataX流量(MB/s) | DataX機器網卡進入流量(MB/s) | DataX機器運行負載 | DB網卡流出流量(MB/s) | DB運行負載 |
---|---|---|---|---|---|---|---|
1 | 否 | 183185 | 18.11 | 29 | 0.6 | 31 | 0.6 |
1 | 是 | 183185 | 18.11 | 29 | 0.6 | 31 | 0.6 |
4 | 否 | 183185 | 18.11 | 29 | 0.6 | 31 | 0.6 |
4 | 是 | 329733 | 32.60 | 58 | 0.8 | 60 | 0.76 |
8 | 否 | 183185 | 18.11 | 29 | 0.6 | 31 | 0.6 |
8 | 是 | 549556 | 54.33 | 115 | 1.46 | 120 | 0.78 |
說明:
- 這里的單表,主鍵類型為 bigint(20),范圍為:190247559466810-570722244711460,從主鍵范圍划分看,數據分布均勻。
- 對單表如果沒有安裝主鍵切分,那么配置通道個數不會提升速度,效果與1個通道一樣。
4.2.2 分表測試報告(2個分庫,每個分庫16張分表,共計32張分表)
通道數 | DataX速度(Rec/s) | DataX流量(MB/s) | DataX機器網卡進入流量(MB/s) | DataX機器運行負載 | DB網卡流出流量(MB/s) | DB運行負載 |
---|---|---|---|---|---|---|
1 | 202241 | 20.06 | 31.5 | 1.0 | 32 | 1.1 |
4 | 726358 | 72.04 | 123.9 | 3.1 | 132 | 3.6 |
8 | 1074405 | 106.56 | 197 | 5.5 | 205 | 5.1 |
16 | 1227892 | 121.79 | 229.2 | 8.1 | 233 | 7.3 |
5 約束限制
5.1 主備同步數據恢復問題
主備同步問題指Mysql使用主從災備,備庫從主庫不間斷通過binlog恢復數據。由於主備數據同步存在一定的時間差,特別在於某些特定情況,例如網絡延遲等問題,導致備庫同步恢復的數據與主庫有較大差別,導致從備庫同步的數據不是一份當前時間的完整鏡像。
針對這個問題,我們提供了preSql功能,該功能待補充。
5.2 一致性約束
Mysql在數據存儲划分中屬於RDBMS系統,對外可以提供強一致性數據查詢接口。例如當一次同步任務啟動運行過程中,當該庫存在其他數據寫入方寫入數據時,MysqlReader完全不會獲取到寫入更新數據,這是由於數據庫本身的快照特性決定的。關於數據庫快照特性,請參看MVCC Wikipedia
上述是在MysqlReader單線程模型下數據同步一致性的特性,由於MysqlReader可以根據用戶配置信息使用了並發數據抽取,因此不能嚴格保證數據一致性:當MysqlReader根據splitPk進行數據切分后,會先后啟動多個並發任務完成數據同步。由於多個並發任務相互之間不屬於同一個讀事務,同時多個並發任務存在時間間隔。因此這份數據並不是完整的
、一致的
數據快照信息。
針對多線程的一致性快照需求,在技術上目前無法實現,只能從工程角度解決,工程化的方式存在取舍,我們提供幾個解決思路給用戶,用戶可以自行選擇:
-
使用單線程同步,即不再進行數據切片。缺點是速度比較慢,但是能夠很好保證一致性。
-
關閉其他數據寫入方,保證當前數據為靜態數據,例如,鎖表、關閉備庫同步等等。缺點是可能影響在線業務。
5.3 數據庫編碼問題
Mysql本身的編碼設置非常靈活,包括指定編碼到庫、表、字段級別,甚至可以均不同編碼。優先級從高到低為字段、表、庫、實例。我們不推薦數據庫用戶設置如此混亂的編碼,最好在庫級別就統一到UTF-8。
MysqlReader底層使用JDBC進行數據抽取,JDBC天然適配各類編碼,並在底層進行了編碼轉換。因此MysqlReader不需用戶指定編碼,可以自動獲取編碼並轉碼。
對於Mysql底層寫入編碼和其設定的編碼不一致的混亂情況,MysqlReader對此無法識別,對此也無法提供解決方案,對於這類情況,導出有可能為亂碼
。
5.4 增量數據同步
MysqlReader使用JDBC SELECT語句完成數據抽取工作,因此可以使用SELECT...WHERE...進行增量數據抽取,方式有多種:
- 數據庫在線應用寫入數據庫時,填充modify字段為更改時間戳,包括新增、更新、刪除(邏輯刪)。對於這類應用,MysqlReader只需要WHERE條件跟上一同步階段時間戳即可。
- 對於新增流水型數據,MysqlReader可以WHERE條件后跟上一階段最大自增ID即可。
對於業務上無字段區分新增、修改數據情況,MysqlReader也無法進行增量數據同步,只能同步全量數據。
5.5 Sql安全性
MysqlReader提供querySql語句交給用戶自己實現SELECT抽取語句,MysqlReader本身對querySql不做任何安全性校驗。這塊交由DataX用戶方自己保證。
6 FAQ
Q: MysqlReader同步報錯,報錯信息為XXX
A: 網絡或者權限問題,請使用mysql命令行測試:
mysql -u<username> -p<password> -h<ip> -D<database> -e "select * from <表名>"
如果上述命令也報錯,那可以證實是環境問題,請聯系你的DBA。