今天從hdfs中導(dǎo)數(shù)據(jù)到mysql,遇到如下錯誤。
com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data too long for column 'is_removed' at row 1 at
最終發(fā)現(xiàn)是因為hdfs中數(shù)據(jù)表字段是46個,而本地數(shù)據(jù)表字段是48個,比hdfs中多了兩個,可能導(dǎo)致字段映射錯誤,把別的字段誤解析成is_removed字段了(is_removed類型是1個長度的char)。
結(jié)論就是要保證導(dǎo)入的mysql表字段和hdfs中的字段一致。
后來經(jīng)過深入研究,發(fā)現(xiàn)要想正確從hive導(dǎo)數(shù)據(jù)到mysql,要保證如下兩個條件
1、hive中的表字段數(shù)目和目標(biāo)mysql表字段數(shù)目一致
2、 hive中的表字段和目標(biāo)mysql表字段名稱對齊,即順序一致
原因如下,查看執(zhí)行sqoop執(zhí)行時產(chǎn)生的java代碼:

sqoop執(zhí)行map時是將hive數(shù)據(jù)文件的一行按順序解析成了一個String List,然后按順序解析為相應(yīng)的字段,主要,這里是按索引解析為對應(yīng)字段,而不是按字段名稱映射。
然后解析完成后,按照下面的方式組裝map插入數(shù)據(jù)庫。

那么,重點來了,程序是從哪里拿到的表字段名們呢?要知道,export源數(shù)據(jù)是存在hdfs文件里的,里面沒有任何字段名的信息!有的只是一行一行的數(shù)據(jù)。hive里之所以有字段信息是因為hive表的表信息存在hive元信息里。所以,我猜測,sqoop是從目標(biāo)mysql數(shù)據(jù)庫里取的列字段信息,然后每解析一行數(shù)據(jù),就按順序解析為目標(biāo)mysql中對應(yīng)的字段(以及字段類型)。最后進(jìn)行insert。
由這兩個過程可知,其是按照默認(rèn)字段索引順序來映射字段的,所以如果字段順序不一致,或者數(shù)目不一致,很可能導(dǎo)致錯位,插入類型解析失敗等錯誤。
由sqoop腳本的配置里也可以看出,sqoop只和hdfs和目標(biāo)mysql交互,不涉及hive,所以只能是從mysql里查找出所以的字段信息。
查詢mysql表的字段信息:
mysql> SHOW FULL COLUMNS FROM subscribe;
+-------------------+-------------+--------------------+------+-----+-------------------+----------------+---------------------------------+-----------------------+
| Field | Type | Collation | Null | Key | Default | Extra | Privileges | Comment |
+-------------------+-------------+--------------------+------+-----+-------------------+----------------+---------------------------------+-----------------------+
| id | bigint(20) | NULL | NO | PRI | NULL | auto_increment | select,insert,update,references | 主鍵 |
| user_id | bigint(20) | NULL | YES | MUL | NULL | | select,insert,update,references | 訂閱者用戶id |
| type | int(11) | NULL | YES | | NULL | | select,insert,update,references | 訂閱類型 |
| subordinate | varchar(64) | utf8mb4_general_ci | YES | | NULL | | select,insert,update,references | 所屬 |
| trigger_type | int(11) | NULL | YES | | NULL | | select,insert,update,references | 觸發(fā)條件類型 |
| trigger_value | int(11) | NULL | YES | | NULL | | select,insert,update,references | 觸發(fā)值 |
| create_time | datetime | NULL | YES | | CURRENT_TIMESTAMP | | select,insert,update,references | 創(chuàng)建時間 |
| publish_time | datetime | NULL | YES | MUL | NULL | | select,insert,update,references | 發(fā)布時間 |
| last_publish_time | datetime | NULL | YES | | NULL | | select,insert,update,references | 上一次發(fā)布時間 |
| publish_frequency | int(11) | NULL | YES | | NULL | | select,insert,update,references | 發(fā)布頻率 |
| delete_time | datetime | NULL | YES | | NULL | | select,insert,update,references | 刪除時間 |
| is_deleted | tinyint(1) | NULL | YES | | 0 | | select,insert,update,references | 刪除 |
+-------------------+-------------+--------------------+------+-----+-------------------+----------------+---------------------------------+-----------------------+
12 rows in set (0.01 sec)