Hive导出到Mysql中中文乱码的问题

MySQL字符集配置
本文介绍如何在MySQL中正确配置字符集以支持中文等多语言字符,包括临时设置和永久更改字符集的方法,以及如何解决因字符集不匹配导致的数据导入问题。

一、mysql中的编码

 

mysql> show variables like 'collation_%';
+----------------------+-------------------+
| Variable_name | Value |
+----------------------+-------------------+
| collation_connection | latin1_swedish_ci |
| collation_database | latin1_swedish_ci |
| collation_server | latin1_swedish_ci |
+----------------------+-------------------+
3 rows in set (0.00 sec)
mysql> show variables like 'character_set_%';
+--------------------------+----------------------------+

| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | latin1 |
| character_set_connection | latin1 |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | latin1 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)

可见原来缺省是latin1编码,会导致中文乱码。

可以在mysql中设置编码,单个设置
mysql> alter database name character set utf8;
mysql> set character_set_connection=utf8;

Query OK, 0 rows affected (0.00 sec)
mysql> set character_set_connection=utf8;
Query OK, 0 rows affected (0.00 sec)
mysql> set character_set_results=utf8;
Query OK, 0 rows affected (0.00 sec)
mysql> set character_set_server=utf8;
Query OK, 0 rows affected (0.00 sec)
但重启后会失效。

 

可以修改配置文件:

[root@Hadoop48 ~]# vi /etc/my.cnf
[mysql]
default-character-set=utf8
[client]
default-character-set=utf8
[mysqld]
default-character-set=utf8
character_set_server=utf8
init_connect='SET NAMES utf8'

重启mysql,这样确保缺省编码是utf8

[root@Hadoop48 ~]# service mysqld restart

查看是否变成utf8:

mysql> \s
--------------
mysql Ver 14.12 Distrib 5.0.95, for redhat-linux-gnu (x86_64) using readline 5.1

Connection id: 2
Current database: toplists
Current user: root@localhost
SSL: Not in use
Current pager: stdout
Using outfile: ''
Using delimiter: ;
Server version: 5.0.95 Source distribution
Protocol version: 10
Connection: Localhost via UNIX socket
Server characterset: utf8
Db characterset: utf8
Client characterset: utf8
Conn. characterset: utf8
UNIX socket: /var/lib/mysql/mysql.sock
Uptime: 39 sec

Threads: 1 Questions: 12 Slow queries: 0 Opens: 15 Flush tables: 1 Open tables: 9 Queries per second avg: 0.308
--------------

mysql> show variables like "char%";
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | utf8 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | utf8 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)

mysql> show variables like "colla%";
+----------------------+-----------------+
| Variable_name | Value |
+----------------------+-----------------+
| collation_connection | utf8_general_ci |
| collation_database | utf8_general_ci |
| collation_server | utf8_general_ci |
+----------------------+-----------------+
3 rows in set (0.00 sec)

将mysql编码改成utf8,并在命令行中指定编码为utf8,执行导出报错:

[zhouhh@Hadoop46 ~]$ sqoop export --connect "jdbc:mysql://Hadoop48/toplists?useUnicode=true&characterEncoding=utf-8" -m 1 --table award --export-dir /user/hive/warehouse/hive_myaward/000000_0 --input-null-string "\\\\N" --input-null-non-string "\\\\N" --input-fields-terminated-by "\\01" --input-lines-terminated-by "\\n"

12/07/20 13:17:22 INFO mapred.JobClient: Task Id : attempt_201207191159_0233_m_000000_0, Status : FAILED
java.io.IOException: java.sql.SQLException: Incorrect string value: '\xE6\x9D\x80\xE7\xA0\xB4...' for column 'nick' at row 1

 

原来我创建的表缺省编码不是utf8的,也需改变一下。

mysql> ALTER TABLE award CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0

再导出

[zhouhh@Hadoop46 ~]$ sqoop export --connect "jdbc:mysql://Hadoop48/toplists?useUnicode=true&characterEncoding=utf-8" -m 1 --table award --export-dir /user/hive/warehouse/hive_myaward/000000_0 --input-null-string "\\\\N" --input-null-non-string "\\\\N" --input-fields-terminated-by "\\01" --input-lines-terminated-by "\\n"
...
12/07/20 14:03:10 INFO mapred.JobClient: map 0% reduce 0%
12/07/20 14:03:24 INFO mapred.JobClient: map 100% reduce 0%
...
12/07/20 14:03:29 INFO mapreduce.ExportJobBase: Exported 2 record
检查表
mysql> select * from award;
+-------------------------------+-----------+-----------+------+-----------+-----------+--------+------+-------------+-----------------+---------+
| rowkey | productid | matchid | rank | tourneyid | userid | gameid | gold | loginid | nick | plat |
+-------------------------------+-----------+-----------+------+-----------+-----------+--------+------+-------------+-----------------+---------+
| 2012-04-27 06:55:00:402713629 | 5947 | 433203828 | 2 | 4027102 | 402713629 | 1001 | NULL | 715878221 | 杀破天A | ios |
| 2012-04-27 06:55:00:406788559 | 778 | 433203930 | 19 | 4017780 | 406788559 | 1001 | 1 | 13835155880 | 亲牛牛旦旦 | android |
+-------------------------------+-----------+-----------+------+-----------+-----------+--------+------+-------------+-----------------+---------+
2 rows in set (0.00 sec)

 

中文编码问题解决。


<think>我们正在处理的问题Hive导出数据到MySQL时,列数不一致导致数据串行错误。根据引用[4]和引用[5]的相关内容,类似的问题通常是由于数据中包含特殊字符(如换行符、分隔符)导致的,或者字符集不匹配。引用[4]提到:从SqlServer同步数据到Hive时,数据错乱(被拆分成多行)是因为源数据中含有Hive的分隔符(换行符)。同理,在Hive导出MySQL时,如果数据中包含MySQL的字段分隔符(如制表符、换行符等)或行分隔符(换行符),就可能导致列数不一致和数据串行。引用[5]提到:在导出时出现乱码问题,通过设置MySQL的字符集为utf8解决。所以字符集问题也可能导致数据解析错误。因此,解决方案可以从两个方面考虑:1.处理数据中的特殊字符,避免它们被误解析为分隔符。2.确保HiveMySQL的字符集一致。具体步骤:第一步:检查并清理数据中的特殊字符在Hive中,导出数据到MySQL之前,应该确保数据中不包含可能被误解析为分隔符的字符(如换行符、制表符等)。常见的做法是替换掉这些字符。例如,我们可以使用Hive的`regexp_replace`函数来替换掉字段中的换行符和制表符:```sqlSELECTregexp_replace(column1,'\n|\t','')AScolumn1_cleaned,regexp_replace(column2,'\n|\t','')AScolumn2_cleaned,...FROMyour_table;```第二步:在Sqoop导出命令中指定分隔符和转义字符使用Sqoop导出时,可以通过参数指定分隔符,并确保使用转义字符来处理字段中的特殊字符。例如:```bashsqoopexport\--connectjdbc:mysql://mysql_host/database\--usernameuser\--passwordpass\--tabletarget_table\--export-dir/hive/path/to/data\--input-fields-terminated-by'\001'#使用Hive默认的分隔符(Ctrl-A),这样就不会与数据中的制表符或换行符冲突--input-lines-terminated-by'\n'#行分隔符,通常为换行符,但要注意数据中不应该有换行符```注意:如果第一步已经清理了换行符和制表符,那么第二步使用默认分隔符即可。但是,如果数据中可能有其他特殊字符,可以考虑使用Hive中较少出现的字符作为分隔符(如Ctrl-A,即\001)。第三步:确保字符集一致在MySQL中创建数据库和表时,指定字符集为utf8(或utf8mb4),以匹配Hive数据的字符集(通常也是utf8)。如引用[5]所示:```sqlCREATEDATABASEIFNOTEXISTSyour_dbDEFAULTCHARACTERSETutf8COLLATEutf8_general_ci;CREATETABLEIFNOTEXISTSyour_table(...)charsetutf8collateutf8_general_ci;```第四步:使用Sqoop的--input-null-string和--input-null-non-string参数处理空值如果数据中有空值,也需要指定空值的表示方式,避免因为空值导致列错位。例如:```bash--input-null-string'\\\\N'\--input-null-non-string'\\\\N'```第五步:测试与调试可以先导出少量数据测试,观察是否还有错位问题。如果问题仍然存在,检查Sqoop的日志(如引用[3]中提到的)以确定错误原因。综上所述,解决Hive导出数据到MySQL时列数不一致导致串行的问题,主要从数据清洗(去除特殊字符)、指定正确的分隔符和字符集设置三个方面入手。生成相关问题:1.如何防止Hive数据中的特殊字符导致导出MySQL时格式错误?2.在Sqoop导出过程中,如何设置分隔符和转义字符以避免数据串行?3.如何设置MySQL的字符集以匹配Hive导出的数据?4.使用Sqoop导出时如何处理空值问题?5.除了Sqoop,还有其他工具可以将Hive数据导出MySQL吗?它们如何避免数据串行?</think>### Hive导出数据到MySQL列数不一致导致串行错误的解决方案 当Hive数据导出MySQL时出现列数不一致和数据串行错误,通常由以下原因导致: 1. **特殊字符问题** - Hive数据中包含换行符`\n`或制表符`\t`(常见于文本字段),会被MySQL误解析为行/列分隔符[^1][^4] - 解决方案: ```sql -- 在Hive中预处理数据:替换特殊字符 SELECT regexp_replace(col1, '\n|\t', ' ') AS col1_clean, regexp_replace(col2, '\n|\t', ' ') AS col2_clean FROM source_table; ``` 2. **分隔符不匹配** - Hive的默认分隔符`\001`与MySQL不兼容 - 解决方案(Sqoop导出命令): ```bash sqoop export \ --connect jdbc:mysql://host/db \ --username user \ --password pass \ --table target_table \ --export-dir /hive/path \ --input-fields-terminated-by '\t' # 显式指定制表符分隔 --input-lines-terminated-by '\n' # 显式指定换行符 ``` 3. **字符集不一致** - Hive(UTF-8)与MySQL字符集不匹配导致乱码和列错位[^5] - 解决方案: ```sql -- MySQL建表时指定UTF-8 CREATE TABLE target_table ( col1 VARCHAR(50), col2 INT ) DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci; ``` 4. **列顺序/数据类型不匹配** - 解决方案: ```bash # 在Sqoop中显式映射列 sqoop export \ --columns "col1,col2,col3" \ # 指定导出列顺序 --map-column-java col1=String,col2=Integer ``` 5. **数据清洗建议** - 导出前在Hive中执行数据质量检查: ```sql -- 检查列数一致性 SELECT COUNT(DISTINCT size(split(line, '\t'))) AS col_count FROM source_table; ``` **完整解决方案步骤**: 1. 在Hive中预处理数据:`regexp_replace()`过滤特殊字符 2. 验证MySQL表结构与Hive schema完全匹配(列数+数据类型) 3. Sqoop导出时明确指定: ```bash --input-fields-terminated-by '\t' --input-lines-terminated-by '\n' --columns "col1,col2,..." ``` 4. MySQL表必须使用`DEFAULT CHARSET=utf8` 5. 小批量数据测试验证后再全量导出 > **关键提示**:当源数据包含自由文本(如用户评论、日志内容)时,特殊字符处理是避免串行错误的核心[^1][^4]。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值