今天又重新搭建了一遍 Hadoop 和 Hive 运行环境,搭建过程中虽然遇到不少问题,但几乎都是之前已经遇到过的,算是都轻易化解了。但是,最后在测试 Hive 环境时,遇到了问题。
在 Hive 的终端下,执行 show tables
,错误信息如下:
hive> show tables; FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask. java.lang.RuntimeException: Unable to instantiate org.apache.hadoop.hive.metastore.HiveMetaStoreClient
这个错误并不陌生。为了得到更精确的错误信息,执行命令:
$ hive --service metastore
错误信息如下(简化版,更完整的错误信息在此):
Exception in thread "main" javax.jdo.JDODataStoreException: Error(s) were found while auto-creating/validating the datastore for classes. The errors are printed in the log, and are attached to this exception. NestedThrowablesStackTrace: java.sql.SQLException: The table 'DBS' is full ... java.sql.SQLException: The table 'DATABASE_PARAMS' is full
需要说明一点,配置 Hive 时采用的元数据库是 MySQL。根据错误信息来看,我觉得问题应该出在 Hive 或 MySQL 这一层。在 MySQL 的终端下,show tables
可以看到一些表确实没有被创建。
随便重试几次,发现问题依旧;然后,想到可能是有残留信息(Hive 的整个安装目录是从一台已配置成功的服务器上同步过来的)的缘故,于是改用原始的 Hive 安装包,只保留几个纯文本的配置文件,问题依旧;反复换各种关键词 Google,无果。
……
转机发生在 df
命令的执行结果上,由于这台 master 结点硬盘空间比较小(10G 多点儿),而且分区很不合理,所以需要经常观察磁盘占用率。df -hT
,执行结果如下:
hduser@master:/$ df -hT Filesystem Type Size Used Avail Use% Mounted on /dev/mapper/wa205-root ext4 2.3G 1.9G 315M 86% / udev devtmpfs 2.0G 4.0K 2.0G 1% /dev tmpfs tmpfs 811M 240K 811M 1% /run none tmpfs 5.0M 0 5.0M 0% /run/lock none tmpfs 2.0G 0 2.0G 0% /run/shm /dev/sda1 ext2 228M 25M 192M 12% /boot /dev/mapper/wa205-home ext4 5.2G 2.1G 2.9G 42% /home overflow tmpfs 1.0M 832K 192K 82% /tmp /dev/sdb1 ext4 2.3G 1.9G 315M 86% /
不难发现,/tmp
目录挂载结果很奇怪:文件系统类型为 overflow
;大小仅 1M;用 lsblk
命令看不到对应的物理磁盘分区。
再次 Google 之,有收获:0 , 1 , 2 , 3 , 4 , 5 , 6
说下我的理解:
/tmp overflow
是一种保护机制,是为了应对磁盘空间不足的状况:当没有给/tmp
单独分区且根目录/
使用率过高时,通过限制/tmp
目录的大小来节省磁盘空间。如果/tmp
是单独分区的,则没有该现象。- 限制大小默认为 1M。
/tmp
对应的是 ram memory,不是真实的物理磁盘分区,用lsblk
自然看不到。
按照上面链接提供的方法,禁用 /tmp overflow
这一 feature/bug:
- 停止 MySQL daemon(因为 MySQL daemon 使用了
/tmp
目录):service mysql stop
- 查看还有哪些程序占用了
/tmp
目录(需要自己分别处理之):lsof /tmp
- 卸载
/tmp
目录:umount /tmp
- 禁用
/tmp overflow
:echo 'MINTMPKB=0' > /etc/default/mountoverflowtmp
OK! /tmp overflow
禁用掉了,Hive 也正常了。
至于原因嘛,应该是 Hive 运行时产生的日志文件(多个)在 /tmp/hadoop_user/
目录下,由于 /tmp
大小受限制、空间已满,导致 Hive 无法正常工作,也无法向 MySQL 中写入元数据。
接下来开始吐槽。
先吐槽 Hive。错误信息不搭边,跟实际原因没什么关联,反而有误导。当然,其实大部分时侯,从 Hive 的错误信息还是能看出些端倪来的。
再喷 /tmp overflow
:
- 不会自动取消,只能手动处理掉。也就是说,如果你的机器曾经出现了该问题,那么即使以后你的磁盘空间又变得充足了,该问题依然存在、不会自动取消,直到你自己手动解决掉这个问题。
- 默认上限 1M,显然太小了。多运行几个程序,或者较长时间不关机,
/tmp
目录很有可能会塞满、进而导致某些程序出错。 - 它是在用一种不合理(dirty?)的方法来避免某一问题的发生,而没有意识到它本身却成了问题。如上所述,这种机制本身就有可能成为问题(从前文 Google 出来的几个链接也可以看出来),而且这个问题出现在它试图解决的那个问题(根目录
/
磁盘占用率过高)之前。难不成它是想以这种「用心良苦」的方式来提醒用户根目录磁盘占用率过高? - 试图避免(也可以理解为「隐藏」)问题,不符合 Fail fast 的理念。与其隐藏问题、「苟延残喘」地运行着,不如尽早暴露问题,用户也有机会更早地意识到并解决它。
- 增加了解决问题的复杂度。如果问题仅仅是磁盘空间占满,你会怎么做呢?
df
发现问题后,删掉磁盘上不再需要的文件,或者增加磁盘空间(物理机,可以挂载一块儿新硬盘;虚拟机,调大磁盘空间)即可。但是如果你是第一次遇到/tmp overflow
的问题呢?你需要 Google 了解什么是/tmp overflow
、为什么会产生该现象、应该如何解决它……而且,最终你还是得面对并解决磁盘空间不足的问题。
总的来说,我觉得 /tmp overflow
这一机制是在制造更多的问题,却没能解决原有的问题。磁盘空间不足的问题偶有发生,在没有发现更好的方法之前,我宁愿自己手动管理解决此类问题,而不是用 /tmp overflow
这种「自以为是」的奇怪方法。
其它关于 /tmp overflow
:
/tmp overflow
机制在 Debian Squeeze 和 Ubuntu server 12.04 上有,其它 Linux 环境暂时未知。
设置 /tmp overflow
大小上限:
sudo mount -t tmpfs -o size=1048576,mode=1777 overflow /tmp
本文环境:Ubuntu 12.04 LTS,64 位