Sqoop export 数据表字段不一致问题

今天从hdfs中导数据到mysql,遇到如下错误。

com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data too long for column 'is_removed' at row 1 at 

最终发现是因为hdfs中数据表字段是46个,而本地数据表字段是48个,比hdfs中多了两个,可能导致字段映射错误,把别的字段误解析成is_removed字段了(is_removed类型是1个长度的char)。

结论就是要保证导入的mysql表字段和hdfs中的字段一致。

后来经过深入研究,发现要想正确从hive导数据到mysql,要保证如下两个条件

1、hive中的表字段数目和目标mysql表字段数目一致
2、 hive中的表字段和目标mysql表字段名称对齐,即顺序一致

原因如下,查看执行sqoop执行时产生的java代码:


image.png

sqoop执行map时是将hive数据文件的一行按顺序解析成了一个String List,然后按顺序解析为相应的字段,主要,这里是按索引解析为对应字段,而不是按字段名称映射。

然后解析完成后,按照下面的方式组装map插入数据库。


img.png

那么,重点来了,程序是从哪里拿到的表字段名们呢?要知道,export源数据是存在hdfs文件里的,里面没有任何字段名的信息!有的只是一行一行的数据。hive里之所以有字段信息是因为hive表的表信息存在hive元信息里。所以,我猜测,sqoop是从目标mysql数据库里取的列字段信息,然后每解析一行数据,就按顺序解析为目标mysql中对应的字段(以及字段类型)。最后进行insert。

由这两个过程可知,其是按照默认字段索引顺序来映射字段的,所以如果字段顺序不一致,或者数目不一致,很可能导致错位,插入类型解析失败等错误。

由sqoop脚本的配置里也可以看出,sqoop只和hdfs和目标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 | 触发条件类型          |
| trigger_value     | int(11)     | NULL               | YES  |     | NULL              |                | select,insert,update,references | 触发值                |
| create_time       | datetime    | NULL               | YES  |     | CURRENT_TIMESTAMP |                | select,insert,update,references | 创建时间              |
| publish_time      | datetime    | NULL               | YES  | MUL | NULL              |                | select,insert,update,references | 发布时间              |
| last_publish_time | datetime    | NULL               | YES  |     | NULL              |                | select,insert,update,references | 上一次发布时间        |
| publish_frequency | int(11)     | NULL               | YES  |     | NULL              |                | select,insert,update,references | 发布频率              |
| 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)

你可能感兴趣的:(Sqoop export 数据表字段不一致问题)