首页 > 解决方案 > SparkSQL(Databricks):将数据插入到由不同角色创建的雪花表中

问题描述

MYSCHEMA.TEST_SNOWFLAKE_ROLE_T在 Snowflake 中有一个使用该角色创建的表CONSOLE_USER.

MYSCHEMA有一个FUTURE GRANTS与之关联的,它BATCH_USER为在模式下创建的任何表的角色授予以下权限MYSCHEMA - DELETE, INSERT, REFERENCES, SELECT, TRUNCATE, UPDATE.

该角色BATCH_USER还具有架构上CREATE STAGEUSAGE权限MYSCHEMA

属于该角色的第二个用户BATCH_USER尝试使用以下 Spark SQL (Databricks) 将数据从数据帧插入到同一个表中,但失败并显示权限不足错误消息。

df.write.mode(op_mode)                   \ 
  .format("snowflake")                   \ 
  .options(**self.sfoptions)             \
  .option("dbtable", snowflake_tbl_name) \
  .option("truncate_table", "on")        \
  .save

出现以下错误消息:

Py4JJavaError: An error occurred while calling o908.save.
   : net.snowflake.client.jdbc.SnowflakeSQLException: SQL access control error
   : Insufficient privileges to operate on table 'TEST_SNOWFLAKE_ROLE_T')

该角色CONSOLE_USER对表具有所有权,因此该角色BATCH_USER将无法删除该表,但添加该选项option("truncate_table", "on")应该可以防止自动覆盖表模式。

我已经多次浏览了可用的 Snowflake 和 Databricks 文档,但似乎无法弄清楚是什么导致了权限不足的问题。

任何帮助深表感谢!

标签: pysparkapache-spark-sqlprivilegessnowflake-cloud-data-platform

解决方案


我最终想通了。

发生错误是因为该表是由角色创建的,该角色CONSOLE_USER保留了对该表的所有权权限。

Snowflake 的 Spark 连接器使用临时表来写入数据。如果数据加载操作成功,则删除原始目标表并将临时表重命名为原始目标表的名称。

现在,为了重命名表或交换两个表,用于执行操作的角色必须对表具有 OWNERSHIP 权限。在上述情况下,所有权从未转移给角色BATCH_USER,因此出现错误。

df.write.mode(op_mode)                   \ 
  .format("snowflake")                   \ 
  .options(**self.sfoptions)             \
  .option("dbtable", snowflake_tbl_name) \
  .option("truncate_table", "on")        \
  .option("usestagingtable", "off")      \
  .save

解决方案是完全避免使用临时表,尽管按照文档,Snowflake 强烈建议使用一个。


推荐阅读