序言
无论是使用何种语言进行编程,碰到的第一个问题莫过于乱码的问题,而使用数据库的时候,也大致差不多。
hive使用元数据库来记录相关hdfs数据文件和数据库表之间的映射关系,当创建的数据库是使用中文注释的时候,那么就会碰到乱码问题。
HIVE元数据库乱码
1 问题现象
创建一个ods层的表,使用中文进行注释,发现不能显示乱码:
2 检查元数据库编码
数据库显示为乱码,第一时间检查元数据库的编码,看是否是utf8编码。
发现数据库编码为latin1,从而要将数据库编码修改为utf8.
代码语言:javascript复制//修改mysql的配置文件my.cnf,在mysqld的配置下加上字符编码为utf8
[root@KEL1 ~]# diff /etc/my.cnf /etc/my.cnf.bak
28,32d27
< character-set-server=utf8
< [client]
< default-character-set=utf8
< [mysql]
< default-character-set=utf8
//重启mysqld进程
[root@KEL1 ~]# systemctl restart mysqld
//检查配置是否生效
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.01 sec)
//删除hive的元数据库,进行重新初始化
mysql> drop database hive;
Query OK, 53 rows affected (0.12 sec)
3 重新初始化元数据库
使用schemtool工具进行重新初始化元数据库:
代码语言:javascript复制[root@KEL1 bin]# schematool -dbType mysql -initSchema
Metastore connection URL: jdbc:mysql://localhost:3306/hive?createDatabaseIfNotExist=true
Metastore Connection Driver : com.mysql.cj.jdbc.Driver
Metastore connection User: root
Starting metastore schema initialization to 1.2.0
Initialization script hive-schema-1.2.0.mysql.sql
Initialization script completed
schemaTool completed
检查数据库的字符编码:
检查表的编码:
代码语言:javascript复制mysql> show create table PARTITIONS;
发现表的编码依旧没发生变化,所以此时去使用中文的时候,其实依旧会出现乱码。
4 检查初始化脚本
在进行初始化的时候,可以看到下面一句话,表示初始化脚本的名称:
代码语言:javascript复制Initialization script hive-schema-1.2.0.mysql.sql
//找到脚本所在的路径
[root@KEL1 apache-hive-1.2.2]# cd scripts/metastore/upgrade/mysql/
[root@KEL1 mysql]# ls -l hive-schema-1.2.0.mysql.sql
-rw-r--r-- 1 root root 35192 Feb 22 04:45 hive-schema-1.2.0.mysql.sql
查看其中的内容:
可以看到建表语句中,指定了字符集。
使用sed命令替换建表语句中的字符集:
代码语言:javascript复制[root@KEL1 mysql]# sed -i 's/CHARSET=latin1/CHARSET=utf8/g' *.sql
[root@KEL1 mysql]# sed -i 's/latin1_bin/utf8_general_ci/g' *.sql
[root@KEL1 mysql]# sed -i 's/latin1/utf8/g' *.sql
检查是否替换成功:
5 重新初始化
重新初始化执行命令如下:
代码语言:javascript复制[root@KEL1 bin]# schematool -dbType mysql -initSchema
Metastore connection URL: jdbc:mysql://localhost:3306/hive?createDatabaseIfNotExist=true
Metastore Connection Driver : com.mysql.cj.jdbc.Driver
Metastore connection User: root
Starting metastore schema initialization to 1.2.0
Initialization script hive-schema-1.2.0.mysql.sql
Error: Specified key was too long; max key length is 3072 bytes (state=42000,code=1071)
org.apache.hadoop.hive.metastore.HiveMetaException: Schema initialization FAILED! Metastore state would be inconsistent !!
*** schemaTool failed ***
发现出现报错创建索引超出长度导致元数据状态不一致。
代码语言:javascript复制//组成索引列总长度大于3072 bytes时报错
CREATE INDEX PCS_STATS_IDX ON PART_COL_STATS (DB_NAME,TABLE_NAME,COLUMN_NAME,PARTITION_NAME) USING BTREE;
将表PART_COL_STAS中的PARTION_NAME的长度替换为640即可(否则会导致索引无法创建):
下图上为报错未创建索引,下为正常创建索引:
再次进行初始化成功:
进行检查:
查看元数据库中的信息: