说实话,每次在服务器上配Hive,我都能看到一群人卡在同一个地方:装是装完了,一启动就报错,然后对着元数据库、字符集、依赖Jar包折腾一下午。这篇我直接拿 hive2.3.6 的完整安装流程来讲,从环境准备到元数据库初始化,再到 HiveServer2 验证,全部给你拆开揉碎。适合刚接触数仓、第一次在真实集群上部署 Hive 的人,也适合每次装完就忘、需要一份完整笔记的老手。我尽量把每个步骤背后的"为什么"也写清楚,不然换个版本、换个环境,你照样会栽跟头。
1. 装 Hive 之前,先把这几件事捋清楚
1.1 Hive 2.3.6 在生态里是什么角色
先说人话版:Hive 就是把 SQL 翻译成 MapReduce(或者 Tez)任务的一个翻译官。你不用写 Java,不用硬啃 MapReduce 的 API,只要你习惯写 SQL,就能在 Hadoop 上做离线数据清洗和统计分析。Hive2.3.6 是 2.3 分支里比较稳的一个版本,不像 3.x 那样对 Hadoop 版本有更苛刻的要求,也不像 1.x 那样功能缺失明显,很多老项目和生产环境都停留在这个版本线。
它的核心组件有三块:客户端(CLI / Beeline)、HiveServer2(给 JDBC/ODBC 连的入口)、Metastore(元数据服务)。其中 Metastore 最关键,所有表结构、分区信息、字段类型、数据文件在 HDFS 上的路径,全都要靠它记下来。所以安装 Hive,本质就是在装一个能管理表结构、能帮你跑 SQL 的系统,而它的"账本"需要放在一个独立的数据库里。
1.2 需要准备好的三件套:JDK、Hadoop、MySQL
很多安装教程一上来就让你解压、改配置,忽略了前置环境,导致后面报错时根本分不清是谁的问题。我在实际部署中,要求环境里必须先满足下面三件事:
| 组件 | 版本建议 | 说明 |
|---|---|---|
| JDK | 1.8(8u201 或更高) | Hive2.3.6 官方文档明确标注基于 Java 8 编译,用高版本 JDK 会缺 JAXB 等模块 |
| Hadoop | 2.7.x ~ 3.x | 集群必须已启动,且hdfs dfs -ls /能正常执行 |
| MySQL | 5.7 或 8.0 | 用来存放 Hive 元数据,需要提前建好库和账号 |
这里我特别想强调 JDK 的坑。如果你服务器上默认装了 Java 11 或者 17,直接跑 Hive 大概率会报NoClassDefFoundError: javax/xml/bind/JAXBException,这不是 Hive 的问题,是 Java 模块化之后把 JAXB 从 JDK 里拆出去了。解决办法就两条:要么老老实实装 JDK 8,要么去补 JAXB 依赖。我建议前者,别给自己找麻烦。
Hadoop 这边也要先做一次健康检查。确认namenode和datanode都活着,dfs.replication别是 0,临时目录权限正常。Hive 装好后建表会在 HDFS 上创建/user/hive/warehouse目录,如果连 HDFS 都写不进去,后面每一步都会连锁报错。
提示:很多人喜欢在个人电脑上"单机装 Hadoop + Hive"体验,但 Hive 单机模式跑 MapReduce 会很慢,因为每个任务都要启动 JVM。建议至少用伪分布式模式,至少
datanode是真实进程。
2. 元数据库选 MySQL,这步为什么不能省
2.1 默认 Derby 的坑,新手最容易踩
Hive 2.3.6 解压后不配置任何东西,直接用hive命令进入 CLI,它内部会默认使用 Apache Derby 这个嵌入式数据库来存元数据。听起来很省事对吧?但你用两天就会发现一个极其搞心态的问题:在/opt/hive目录下启动,它会在/opt/hive/metastore_db给你建库;你换个目录再启动,比如跑到/root下执行hive,它又在/root/metastore_db另建一套。你的表"凭空消失"了,其实就是 Derby 换了路径。
再说并发层面。Derby 作为嵌入式数据库,只允许一个进程访问。你一旦启动 HiveServer2,又用 CLI 去连接,两个进程抢同一个库,直接给你抛Failed to start database 'metastore_db'。所以生产环境千万别用 Derby,老老实实上 MySQL。MySQL 是多进程、多客户端都能访问的独立数据库服务,不会出现文件锁这类问题。
注意:Hive 2.3.6 与 MySQL 8.0 配合时,驱动要选
mysql-connector-java 8.0.x,URL 里必须加useSSL=false,不然会频繁报 SSL 连接警告;如果你用 MySQL 5.7,驱动选 5.1.4x 版本最稳。
2.2 MySQL 侧的初始化准备
等 MySQL 服务装好并能本地登录后,执行下面这些 SQL。这里踩过的坑是:有些教程只让你建库,没让你授权,结果 Hive 初始化元数据时,拿hive账号连上去一看权限不够,报Access denied for user。
CREATE DATABASE IF NOT EXISTS hive_metastore CHARACTER SET latin1; CREATE USER 'hive'@'%' IDENTIFIED BY 'Hive@123'; GRANT ALL PRIVILEGES ON hive_metastore.* TO 'hive'@'%'; FLUSH PRIVILEGES;为什么字符集选latin1?不是为了复古,而是因为 Hive 2.3.x 在初始化元数据 Schema 时,生成的表结构和索引有一些长度限制。如果 MySQL 服务端或者数据库用了utf8mb4,建索引时会碰到Specified key was too long; max key length is 767 bytes的经典报错。先选latin1把 Schema 初始化完成,后续如果你业务中确实需要存 emoji 之类的字符,再针对具体业务表调整字符集也不迟。
如果你不想建一个
latin1库,也可以把 MySQL 参数innodb_large_prefix打开,并设置innodb_file_format=Barracuda,让 MySQL 支持更大的索引前缀。但这个方案要改 my.cnf 并重启 MySQL,在已有生产库上动全局配置,风险比较大,我一般只建议新环境这样做。
延伸说一句:账号的 host 不要只写'localhost'。因为你的 Hive 服务和 MySQL 可能在同一台机器上,也可能不在同一台,而且 Hive 通过 JDBC 连接时,TCP 来源 IP 可能会被 MySQL 解析成localhost,也可能不是。直接用'%'最省心,配合后续的防火墙白名单做控制即可。
3. 下载解压与目录规划
3.1 版本选择与文件下载
Hive 的命名有两种,一种是apache-hive-2.3.6-bin.tar.gz,这种是编译好的二进制包;另一种是apache-hive-2.3.6-src.tar.gz,这是源码包,需要自己编译,一般用不到。下载时认准bin后缀,别下错。
下载链接方面,到 Apache 官方下载页选择对应的 CDN 镜像即可。国内服务器从官方主站下载可能速度较慢,选择阿里云或者清华的镜像站会快很多。文件不大,大概 100 MB 左右,所以不用太担心带宽问题。
文件拿到手之后,先做一件事:校验一下 MD5 或者 SHA256。下载源有时会有问题,解压到一半报crc错误或者文件损坏,排查起来非常痛苦。用官方提供的.sha256文件,执行sha256sum apache-hive-2.3.6-bin.tar.gz,对比输出结果,一致再继续。
3.2 安装目录与软链接规划
我习惯把大数据组件统一放在/opt/module下,不用/usr/local,因为后面升级版本时直接换软链接就行,不需要改一堆配置里的绝对路径。具体操作如下:
tar -zxvf apache-hive-2.3.6-bin.tar.gz mv apache-hive-2.3.6-bin /opt/module/hive-2.3.6 ln -s /opt/module/hive-2.3.6 /opt/module/hive这样$HIVE_HOME就指向/opt/module/hive。以后升到 Hive 3.x,只需要解开新包,把软链接换一下,所有配置文件里写的路径如果引用了$HIVE_HOME,就全都自动指向新版。这个习惯帮我省了很多维护时间。
目录规划完,还要建几个后续要用的目录,并确认 HDFS 上也有对应位置:
mkdir -p /opt/module/hive/logs hdfs dfs -mkdir -p /user/hive/warehouse hdfs dfs -mkdir -p /tmp/hive hdfs dfs -chmod -R 777 /tmp/hive hdfs dfs -chmod -R 755 /user/hive/warehouse/tmp/hive是 Hive 执行 MapReduce 任务时存放临时结果、中间文件的目录。权限如果没有放开,运行 SQL 时会报Permission denied,而且这个错出在 YARN 容器里,日志不好找,建议一开始就给足权限。warehouse目录权限可以收紧到 Hive 服务账号,但如果你还在摸索阶段,755 先用着问题不大。
实操心得:如果你的 Hadoop 配置了
dfs.permissions.enabled=true(默认就是 true),Hive 从 HDFS 读写文件的进程身份取决于你启动 Hive 时用的系统用户名。所以我通常单独建一个hive系统账号,用su - hive来启动 HiveServer2,避免权限错乱。用 root 跑也不是不行,但业务规范上不推荐。
4. 配置文件逐个拆解
4.1 hive-site.xml:连接元数据库的核心参数
Hive 解压后默认没有hive-site.xml,只有hive-default.xml.template和hive-log4j2.properties.template。你需要从模板复制一份,再改成自己的配置。别直接改模板文件,后期升级会覆盖掉,到时候哭都来不及。
cp /opt/module/hive/conf/hive-default.xml.template /opt/module/hive/conf/hive-site.xml cp /opt/module/hive/conf/hive-log4j2.properties.template /opt/module/hive/conf/hive-log4j2.properties然后重点配置hive-site.xml里的这几项。很多人喜欢直接把网上贴的一大段 XML 全复制过来,里面有一堆含义不明的参数。我不建议这么干,核心参数就几个,剩下的保持默认即可:
<configuration> <property> <name>javax.jdo.option.ConnectionURL</name> <value>jdbc:mysql://your-mysql-host:3306/hive_metastore?createDatabaseIfNotExist=true&useSSL=false</value> </property> <property> <name>javax.jdo.option.ConnectionDriverName</name> <value>com.mysql.jdbc.Driver</value> </property> <property> <name>javax.jdo.option.ConnectionUserName</name> <value>hive</value> </property> <property> <name>javax.jdo.option.ConnectionPassword</name> <value>Hive@123</value> </property> <property> <name>hive.metastore.warehouse.dir</name> <value>/user/hive/warehouse</value> </property> <property> <name>hive.server2.thrift.bind.host</name> <value>your-hiveserver2-host</value> </property> <property> <name>hive.server2.thrift.port</name> <value>10000</value> </property> <property> <name>hive.metastore.uris</name> <value>thrift://your-metastore-host:9083</value> </property> </configuration>这里重点说两个容易踩坑的地方。第一个,ConnectionDriverName的值要跟你放的 JDBC 驱动包匹配:如果 MySQL 是 5.7、驱动是mysql-connector-java-5.1.4x.jar,驱动类就是com.mysql.jdbc.Driver;如果 MySQL 是 8.0,驱动是mysql-connector-java-8.0.xx.jar,驱动类要写成com.mysql.cj.jdbc.Driver。网上很多老教程只写一个,你复制下来连不上 MySQL,就是因为驱动类名和实际 jar 包不匹配。
第二个,hive.metastore.uris。Hive 的 Metastore 可以内嵌在 Hive CLI、HiveServer2 进程里,也可以独立成一个进程。如果你想要有独立的 metastore 服务,就需要配这个参数,并且另外启动。如果你不配这个参数,HiveServer2 启动时会尝试在本进程内起一个 metastore,也能跑,但不利于后期多个客户端共享和权限隔离。所以我建议采用独立 metastore 的架构。
除了这些,还有几个值得关注但不一定需要改的参数:
| 参数名 | 默认值 | 说明 |
|---|---|---|
hive.execution.engine | mr | 就是 MapReduce,可改为 tez |
hive.support.concurrency | false | 并发操作表时建议开启 |
hive.zookeeper.quorum | 无 | 如果开启 Hive locking,需要 Zookeeper 地址 |
hive.server2.authentication | NONE | 生产环境建议改为 LDAP 或 Kerberos |
hive.server2.thrift.max.worker.threads | 100 | 并发线程数上限,默认够用 |
4.2 环境变量与日志配置
hive-env.sh是从hive-env.sh.template复制出来的,里面主要设置 Java、Hadoop 的路径,也可以顺便设置HIVE_AUX_JARS_PATH。我贴一个我常用的简化版:
export JAVA_HOME=/usr/local/jdk1.8 export HADOOP_HOME=/opt/module/hadoop-2.9.2 export HIVE_HOME=/opt/module/hive # 下面这行很重要:把 Hadoop classpath 传给 Hive export HADOOP_CLASSPATH=$HADOOP_HOME/share/hadoop/common/*:$HADOOP_HOME/share/hadoop/common/lib/*:$HADOOP_HOME/share/hadoop/hdfs/*:$HADOOP_HOME/share/hadoop/hdfs/lib/*:$HADOOP_HOME/share/hadoop/mapreduce/*:$HADOOP_HOME/share/hadoop/mapreduce/lib/*:$HADOOP_HOME/share/hadoop/yarn/*:$HADOOP_HOME/share/hadoop/yarn/lib/*关于HADOOP_CLASSPATH,很多人不设置也能跑,因为 Hive 脚本会自动调用hadoop classpath来获取。但我在某些内网环境、Hadoop 安装路径不规范的情况下遇到过获取不到完整 classpath 的问题,导致 Hive 找不到 Hadoop 的依赖包,直接报ClassNotFoundException。写死到hive-env.sh虽然看起来有点长,但能保证不依赖环境。
日志方面,hive-log4j2.properties里面可以修改日志级别和输出目录。默认日志写在/tmp/用户名/hive.log,这个位置在重启后被系统清理很常见,建议改到/opt/module/hive/logs/hive.log。具体修改方式是把 R 开头的property.hive.log.dir改成你的日志目录。另外把日志级别调成INFO,调成DEBUG的话量太大,排错时会淹没关键信息。
实战心得:Hive 的日志是排查问题的重要抓手。最常见的情况是 HiveServer2 启动失败,你直接看控制台输出的
Exception,但完整堆栈在logs/hiveserver2.log里,控制台只截断了前几行。所以装完先确认日志能不能正常输出,这是个不起眼但特别关键的步骤。
5. 初始化 Schema 与启动验证
5.1 schematool 初始化元数据
配置文件改完,不要急着启动,第一步是初始化元数据库。所谓"初始化",就是在 MySQL 的 hive_metastore 库里把 Hive 自己需要的表结构全建出来,比如VERSION、DBS、TBLS、COLUMNS_V2这些。不执行初始化,直接启动 Hive 会报Table 'hive_metastore.VERSION' doesn't exist,或者MetaException。
执行下面这条命令:
/opt/module/hive/bin/schematool -dbType mysql -initSchema执行过程大概十几秒到几分钟,取决于你机器的 IO 和网络状况。看到schemaTool completed就代表初始化成功。这时候可以去 MySQL 里查一下:
USE hive_metastore; SHOW TABLES; SELECT * FROM VERSION;如果VERSION表里显示2.3.6,说明 Schema 版本和 Hive 版本对上了。如果这里显示的是别的版本,或者执行过程中报错,先别继续,回头检查驱动和 URL。
这里有个很容易忽视的细节:schematool使用的也是hive-site.xml里的连接信息,所以它连不上 MySQL 的概率非常大。常见报错是Could not create a validated object或Communications link failure,前者多是账号密码或权限问题,后者多用useSSL=false或者端口不对解决。
5.2 启动 HiveServer2 并用 beeline 验证
Schema 初始化成功后,我建议按照"先 Metastore、再 HiveServer2"的顺序启动,这样方便观察各自日志。
第一个终端启动 Metastore:
/opt/module/hive/bin/hive --service metastore看到Starting metastore on port 9083后就说明 metastore 起来了。默认端口是 9083,如果你想换,在hive-site.xml里加metastore.uris即可。
第二个终端启动 HiveServer2:
/opt/module/hive/bin/hive --service hiveserver2HiveServer2 启动比较慢,因为它要初始化一堆 Session、权限、连接池配置,CPU 和内存消耗也不小。看到日志输出Starting HiveServer2之后,不要急着马上连接,等半分钟到一分钟,让端口真正监听起来。可以用这个命令确认:
netstat -tlnp | grep 10000看到0.0.0.0:10000监听之后,用 beeline 做连接测试:
/opt/module/hive/bin/beeline !connect jdbc:hive2://your-hiveserver2-host:10000输入用户名和密码。如果你没有额外配置认证,密码随便填,用户名就是当前系统用户名。连上之后执行:
CREATE DATABASE test_db; USE test_db; CREATE TABLE test_table (id INT, name STRING); SHOW TABLES;如果SHOW TABLES能正常返回test_table,说明从客户端到 HiveServer2、再到 Metastore、再到 MySQL 的整条链路都通了。这时候你也可以验证一下数据目录是否创建成功,在 HDFS 上执行:
hdfs dfs -ls /user/hive/warehouse/test_db.db注意:如果
beeline连接时让你输入用户名,但 HiveServer2 是用root启动的,而你当前用户是hadoop,连上之后执行 SQL 有可能会遇到No valid local directory或者 HDFS 权限不足。最简单的方式是让 beeline 连接时用户名也填启动服务那个账号,或者开启hive.server2.enable.doAs相关配置再调整权限。
6. 常见问题与排查速查
6.1 报错二连:连不上 MySQL 与驱动未找到
第一个高频报错是Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure,看着很吓人,其实排查思路很直接:
- MySQL 服务是否在运行:
systemctl status mysqld - 端口是否能连通:
telnet mysql-host 3306 - 账号是否有远程访问权限:
SELECT user, host FROM mysql.user; - URL 里的 host 是否写对:如果 MySQL 在本机,
localhost和 IP 之间也可能有差异
第二个高频报错是java.lang.ClassNotFoundException: com.mysql.jdbc.Driver。原因就是 JDBC 驱动 jar 没放到 Hive 的 lib 目录。Hive 2.3.6 默认不自带 MySQL 驱动,需要手动下载拷贝:
cp mysql-connector-java-5.1.49.jar /opt/module/hive/lib/注意如果 Hive 目录里有其他版本的 connector jar,建议先删掉,避免版本冲突。比如你之前放过 8.0.x,现在又放 5.1.49,Hive 会按扫描顺序加载,加载到哪个是哪个,一旦版本不匹配,很容易出现诡异的连接错误。
6.2 字符集引发的初始化失败
Schema initialization failed或Specified key was too long,这基本就是 MySQL 库的字符集问题。Hive 2.3.6 的表结构里有几个索引字段长度比较大,在utf8mb4下一个字符占 4 字节,索引长度就会超限。解决办法在初始化前改库字符集:
ALTER DATABASE hive_metastore CHARACTER SET latin1;如果你已经初始化到一半失败,数据库里残留了一些表,不要急着重复执行-initSchema,否则会报Table 'DBS' already exists。这时候要么先DROP DATABASE hive_metastore再重建,要么使用-upgradeSchema来继续。我建议直接删库重建,干净省事。
提示:Hive 元数据库本身不需要刻意支持多字节字符集,因为真正的数据内容存在 HDFS 上,元数据库只存表的 schema 和 location 字符串。这些字符串绝大多数是 ASCII 字符,用
latin1完全够用。
6.3 权限与目录问题
Permission denied: user=root, access=WRITE, inode="/tmp/hive":hadoop:supergroup:drwxr-xr-x这种报错,发生在你启动 Hive 时用的系统用户没有 HDFS 对应目录的写权限。解决方式分两步看:要么把目录权限放宽,要么让你启动 Hive 的用户在 HDFS 上有supergroup或对应目录的写权限。最省事的做法是:
hdfs dfs -chmod -R 777 /tmp/hive hdfs dfs -chown -R hive:hive /tmp/hive如果你的hive-site.xml中设置了hive.exec.local.scratchdir以及hive.downloaded.resources.dir,也要确认这些本地目录存在并且可写:
mkdir -p /opt/module/hive/tmp chown -R hive:hive /opt/module/hive/tmp另外还有一个很隐蔽的问题:/tmp/hive和/user/hive/warehouse如果和 Hive 版本不匹配,旧版本残留的derby.log、metastore_db会影响新版本的运行。如果你曾经在某个目录下直接跑过hive命令,旧 Derby 文件会留在那里。所以开始之前最好全盘搜索并删除这些残留:
find / -name "derby.log" -type f 2>/dev/null find / -name "metastore_db" -type d 2>/dev/null find / -name "derby.properties" -type f 2>/dev/null这些文件是新手很容易忽略的。尤其是derby.log,看起来无害,但它会干扰你对日志的判断,而且如果旧 Derby 元数据和你新配置的 MySQL 元数据产生了某种混淆,很容易误导排查方向。
几个容易忽略的细节
我在多次安装中总结出一些"没人告诉你、但很要命"的小细节,集中说一下。
Hive 2.3.6 官方要求的hive.metastore.warehouse.dir默认是/user/hive/warehouse,这本身没问题,但如果你用的 Hadoop 版本是高版本,比如 3.1 以上,HDFS 的trash机制可能会把删掉的数据移动到/user/hive/.Trash,这既不占用仓库空间,也不会影响你的表,但如果磁盘告急,记得清一下。我之前遇到过一次删表后磁盘没释放的假象,排查半天才发现是 trash 机制。
关于hive.support.concurrency和hive.zookeeper.quorum,如果你有多个客户端同时操作同一张表,建议开启,用 Zookeeper 做分布式锁。不开启的话,并发写同一张表,Hive 不会串行阻塞,最后出现数据文件互相覆盖的问题,SQL 也不会报错,只能从结果数据的完整性上发现问题。这类问题非常隐蔽,我在实际项目中碰到过一次线上数据错乱,最后定位到就是因为没有并发控制。单机环境可以不配,但一旦上生产就一定要开。
再有一个是内存和堆大小。HiveServer2 默认的堆内存是 JVM 自动分配的,一般也就 256 MB 左右。你在 beeline 里执行大查询时,HiveServer2 如果挂掉,控制台上经常只显示Connection lost,没太多有效信息。建议在启动脚本里手动设置:
export HADOOP_OPTS="-Xms512m -Xmx2048m" export HIVE_OPTS="-Xms512m -Xmx2048m"这些设置放在hive-env.sh里即可。要不要调大取决于你的并发量和 SQL 复杂度,但至少给到 2 GB,稳定性会有明显提升。
还有一个我很想强调的点:日志时间与时区问题。Hive 默认读取系统时间,如果你服务器时区不是 CST,Hive 元数据里记录的时间戳和实际业务时间会有偏差。统一时区这件事容易被忽略,但排查数据迟延时特别折磨人。可以在启动 Hive 之前先date看一眼系统时间,不对就先调整。
最后,安装目录千万不要有中文或者空格。Hive 的很多脚本会对路径做字符串拼接,一旦路径里有空格,比如/opt/my hive,脚本会把它拆成两个参数,然后报 各种奇怪的错。这个问题在云服务器上偶尔会遇到,因为有些同学买完机器顺手把目录写成了业务名带空格的,排查大半天。我用过一条经验:所有大数据组件的安装路径必须符合^[a-zA-Z0-9_\-/]+$,少一个字符都不行。
如果你严格按照上面的流程走,正常情况下从解压到 beeline 能跑通 SQL,整个过程也就半小时。Hive 2.3.6 这套组合目前依然是很多离线数仓项目的标配,学会它之后转 Hive 3.x 也不会有太大跨度,核心的 metastore 配置逻辑是相通的。后面你可以根据自己的业务场景再慢慢加 Tez 引擎、加 LLAP、配 Kerberos 认证,那些都是在打好的地基上盖房子了。