今天从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代码:
sqoop执行map时是将hive数据文件的一行按顺序解析成了一个String List,然后按顺序解析为相应的字段,主要,这里是按索引解析为对应字段,而不是按字段名称映射。
然后解析完成后,按照下面的方式组装map插入数据库。
那么,重点来了,程序是从哪里拿到的表字段名们呢?要知道,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)