原始连接:https://www.iteblog.com/archives/2166.html
Hive 2017-06-27 08:54:01 3508 1评论 下载为PDF 为什么无法评论和登录
文章目录
问题
我们应该知道,Hive中存在两种类型的表:管理表(Managed table,又称Internal tables)和外部表(External tables),详情请参见《Hive表与外部表》。在公司内,特别是部门之间合作,很可能会通过 HDFS 共享一些 Hive 表数据,这时候我们一般都是参见外部表。比如我们有一个共享目录:/user/iteblog_hadoop/order_info
,然后我们需要创建一个外部表用于分析,如下:
如果想及时了解Spark、Hadoop或者Hbase相关的文章,欢迎关注微信公共帐号:iteblog_hadoop
CREATE EXTERNAL TABLE `order_info`( `user_id` string COMMENT '用户UID' , `order_no` string COMMENT '订单号' , `price` dobule COMMENT '订单金额' , ) LOCATION 'hdfs://iteblogcluster/user/iteblog_hadoop/order_info' |
但是由于某些原因我们可能需要删除这个外部表。遗憾的是,我们会遇到以下的异常:
hive> drop table order_info; FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql. exec .DDLTask. MetaException(message: Table metadata not deleted since hdfs://iteblogcluster/ user /iteblog_hadoop/order_info is not writable by iteblog) |
原因
这是因为 Hive 在删除表的时候会检查当前用户是否对数据目录(本例子为/user/iteblog_hadoop/order_info
)有写权限,代码如下:
if (tbl.getSd().getLocation() != null ) { tblPath = new Path(tbl.getSd().getLocation()); if (!wh.isWritable(tblPath.getParent())) { String target = indexName == null ? "Table" : "Index table" ; throw new MetaException(target + " metadata not deleted since " + tblPath.getParent() + " is not writable by " + hiveConf.getUser()); } } |
一般外部共享给咱们的数据只有读权限,并没有写权限,所以上面的实现逻辑有问题。
解决办法
解决办法大致有两种:
修改 Hive 的源码
,如果当前表是外部表,则不检查当前用户是否对数据目录有写权限。实现如下:
diff --git a/metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java b/metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java index 4520cd52539e26afebf9553ce411c9d4ee03cda0..1ae9b9771617637d8b8b9b16f7c5184d77e28d5a 100644 --- a/metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java +++ b/metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java @@ - 1360 , 13 + 1360 , 20 @@ private void drop_table_core( final RawStore ms, final String dbname, final Strin throw new MetaException(e.getMessage()); } } + isExternal = isExternal(tbl); if (tbl.getSd().getLocation() != null ) { tblPath = new Path(tbl.getSd().getLocation()); - if (!wh.isWritable(tblPath.getParent())) { - throw new MetaException( "Table metadata not deleted since " + - tblPath.getParent() + " is not writable by " + - hiveConf.getUser()); + + //Check that the user is owner of the table + if (!tbl.getOwner().equals(hiveConf.getUser())) { + throw new MetaException( "Table metadata not deleted since user " + hiveConf.getUser() + + " is not the owner of table " + tbl.getTableName()); + } + // if table is internal, check that table location is writable by the user + if (!wh.isWritable(tblPath.getParent())&&!isExternal) { + throw new MetaException( "Table metadata not deleted since " + tblPath.getParent() + + " is not writable by " + hiveConf.getUser()); } } |
上面的代码是摘自HIVE-9020,详情请大家自己进去看。
修改外部表的数据目录
这种办法就是利用 Hive 提供的功能,修改当前外部表(order_info)的数据目录到一个可以写的数据目录下,然后再删除外部表,如下:
hive> alter table order_info set location 'hdfs://iteblogcluster/user/iteblog/tmp/' ; hive> drop table order_info; OK Time taken: 0.254 seconds |
然后我们再删除 order_info
表,这时候就没问题了。
如果外部表带有分区,删除每个分区的时候可能也会报上面的错误,这时候也需要我们修改每个分区的数据目录到一个可写的目录下就可以删除当前分区。
ALTER TABLE order_info PARTITION (dt= '2017-06-27' ) SET LOCATION "new location" ; |
本博客文章除特别声明,全部都是原创!
转载本文请加上:转载自过往记忆(https://www.iteblog.com/)
本文链接: 【Hive删除外部表异常(Table metadata not deleted)】(https://www.iteblog.com/archives/2166.html)