最近在集成hive的时候发现一个问题,现象是这样的,我需要创建一个外部表:

1
2
3
4
5
6
7
8
CREATE EXTERNAL TABLE `inventory3`(
`inv_item_sk` int,
`inv_warehouse_sk` int,
`inv_quantity_on_hand` int)
PARTITIONED BY (
`inv_date_sk` int) STORED AS ORC
LOCATION
'hdfs://master-1:8020/';

就是一个普通的外部表创建,使用beeline连接hive server2去创建也会成功,但是删除的时候却不行,会有如下问题:

1
2
3
4
5
6
7
8
9
10
0: jdbc:hive2://master> drop table inventory3;
INFO : Compiling command(queryId=hive_20220130135301_09abe5e5-7538-4137-b0f7-559f998a3820): drop table inventory3
INFO : Semantic Analysis Completed (retrial = false)
INFO : Returning Hive schema: Schema(fieldSchemas:null, properties:null)
INFO : Completed compiling command(queryId=hive_20220130135301_09abe5e5-7538-4137-b0f7-559f998a3820); Time taken: 0.075 seconds
INFO : Executing command(queryId=hive_20220130135301_09abe5e5-7538-4137-b0f7-559f998a3820): drop table inventory3
INFO : Starting task [Stage-0:DDL] in serial mode
ERROR : FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask. MetaException(message:java.lang.NullPointerException)
INFO : Completed executing command(queryId=hive_20220130135301_09abe5e5-7538-4137-b0f7-559f998a3820); Time taken: 0.097 seconds
Error: Error while processing statement: FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask. MetaException(message:java.lang.NullPointerException) (state=08S01,code=1)

虽然我知道具体的原因,但是还是想看一下源码的流程,所以必须要远程debug一下,远程debug hive的方式我之前写了一篇文章:https://baifachuan.com/posts/6881ba5d.html

通过断点的形式,发现在删除表达是时候会进入:common/src/java/org/apache/hadoop/hive/common/FileUtils.javacheckDeletePermission方法,最终在这个位置:

1
2
3
4
5
6
7
// check if sticky bit is set on the parent dir
FileStatus parStatus = fs.getFileStatus(path.getParent());
if (!shims.hasStickyBit(parStatus.getPermission())) {
// no sticky bit, so write permission on parent dir is sufficient
// no further checks needed
return;
}

会出错,也就是path.getParent() 会返回null,从而导致fs.getFileStatus(path.getParent())出现NPE,这里的原因是因为创建表的时候指定的地址是:hdfs://master-1:8020/

这个地址是跟地址,所以上面在path.getParent()的时候返回的是null,从业务流程上来说,我能创建成功,但是无法删除,这是产品缺陷,hive的修,从修复来说,有2个地方可以修复。

一个是在hive server2的代码里面进行检查,如果是外部表,且地址是跟的话直接拒绝创建,当然也可以在ranger的hive plugin里面去鉴别也行。

另一种是直接修复hdfs的底层fs client,让Path这个对象在getParent的时候返回”/“而不是nul,不过我更倾向于前者修复方式。

因为最近集成到这部分工作,所以打算自己修复一下,然后给hive 提个MR。


扫码手机观看或分享: