我有一个Spark应用程序,我将JSON记录读入DataFrame
,转换数据(即将其展平以用于BI工具),然后将其插入现有的分区Hive表中。 DataFrame
仅包含来自相同分区列的数据,例如x
和y
,而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很好玩?
任何见解?
答案 0 :(得分:1)
所以,我想出了问题:
dude
和组hdfs
创建。有趣的是,hive
和spark
都不是群组hdfs
中的用户; dude
也是不该群组的一部分。出于某种原因,hive
和spark
所属的群组在我们的群集上被称为hadoop
。无论如何,这意味着hive
无法插入,因为默认情况下会忽略ACL(稍后会详细介绍)。我猜测Spark会批量卸载数据,并且在第一批因基本权限而导致问题的情况下卸载数据。spark.acls.enable=true
,在这种情况下,它使用了ACL,因为hadoop
组允许读/写/执行,所以都很好