Hive中的“无法改变分区”来自Spark应用程序

时间:2016-05-04 06:04:05

标签: mysql apache-spark hive

我有一个Spark应用程序,我将JSON记录读入DataFrame,转换数据(即将其展平以用于BI工具),然后将其插入现有的分区Hive表中。 DataFrame仅包含来自相同分区列的数据,例如xy,而PARTITION子句仅包含这些静态值,因此没有ALTER TABLE命令继续。实现它的代码如下所示:

df.registerTempTable("tempTab")
hc.sql(s"USE $schema")
hc.sql(
  s"""INSERT INTO TABLE $table PARTITION (x="$x", y="$y")
      | SELECT * FROM tempTab""".stripMargin)

问题是:当我运行应用程序时,它会插入几百MB的数据然后给我:

ERROR metadata.Hive: org.apache.hadoop.hive.ql.metadata.HiveException: Unable to alter partition.
    at org.apache.hadoop.hive.ql.metadata.Hive.getPartition(Hive.java:1656)
    at org.apache.hadoop.hive.ql.metadata.Hive.loadPartition(Hive.java:1256)

问题是,我没有改变分区,我正在插入它。 来自相同 DataFrame的第一块记录实际上已插入Hive(我已检查过)。

错误似乎是由以下原因引起的:

Caused by: MetaException(message:java.security.AccessControlException: Permission denied: user=hive, access=WRITE, inode="/apps/hive/warehouse/demo.db/demotable/x=foo/y=bar":dude:hdfs:drwxr-xr-x

我们在Spark中使用MySQL作为Metastore和用户模拟。我知道用户模拟不会从Spark内部传递给Hive,但hive用户通过ACL进行rwx访问。我使用hdfs dfs -getfacl /apps/hive/warehouse/demo.db进行了检查,hive所属的群组拥有所有权限。

但是,在日志顶部附近,我看到以下内容:

spark.SecurityManager: SecurityManager: authentication disabled; ui acls disabled; users with view permissions: Set(yarn, dude); users with modify permissions: Set(yarn, dude)

这似乎向我表明ACL已被禁用,只使用了基本权限。令我担心的是,很大一部分数据被插入到Hive中,因此权限问题似乎不太可能恕我直言。我不认为在后台有一项工作会重置权限或类似的奇怪的东西。

我发现this discussion其中一个简单的LOAD语句导致相同的“无法更改分区”异常,它可能是由MySQL作为Metastore引起的。 This post描述了对Metastore负载过高的可能性。

编辑:我刚从Hive中创建了分区,权限与Spark创建的权限不同。有没有办法让Spark很好玩?

任何见解?

1 个答案:

答案 0 :(得分:1)

所以,我想出了问题:

  • 当Spark创建分区时,它使用用户权限创建这些分区,因此在我的情况下为用户dude和组hdfs创建。有趣的是,hivespark都不是群组hdfs中的用户; dude也是该群组的一部分。出于某种原因,hivespark所属的群组在我们的群集上被称为hadoop。无论如何,这意味着hive无法插入,因为默认情况下会忽略ACL(稍后会详细介绍)。我猜测Spark会批量卸载数据,并且在第一批因基本权限而导致问题的情况下卸载数据。
  • 我可以直接在Hive中创建分区,然后Hive使用目录的默认权限。这至少解决了这个问题,但理想情况下,如果需要,我会动态使用Spark来创建它们。
  • 为此,我必须设置参数spark.acls.enable=true,在这种情况下,它使用了ACL,因为hadoop组允许读/写/执行,所以都很好