Spark使用overwrite模式写入Redshift表丢失权限如何解决
默认使用overwrite模式写入Redshift时,Databricks Spark Redshift连接器的默认逻辑是先删除原表、再创建新表写入数据,新表不会继承原表绑定的访问权限,就会出现其他用户丢失select、update权限的问题,可通过以下三种方案解决:
方案1:开启truncate覆写(表结构固定场景首选)
开启连接器的truncate配置后,写入时不会删除原表,只会清空表内原有数据再插入新数据,表结构、绑定的权限会完整保留。
只需要在写入逻辑中新增truncate配置即可:content.write \ .format("com.databricks.spark.redshift") \ .option("aws_iam_role", role_arn) \ .option("url", host) \ .option("user", user) \ .option("password", pass) \ .option("dbtable", "schema.table") \ .option("tempdir", aws_bucket_name) \ .option("truncate", "true") \ .mode("overwrite") \ .save()注意:该模式要求待写入数据的Schema和原表完全一致,否则会抛出写入错误。
方案2:配置postactions自动补全权限(兼容Schema变更场景)
如果写入过程中需要调整表结构,无法使用truncate模式,可以通过连接器的postactions参数,在新表创建完成后自动执行赋权语句,恢复用户/用户组的访问权限。
示例代码如下:# 定义需要恢复的权限语句,多语句用分号分隔 restore_permission_sql = """ GRANT SELECT ON schema.table TO GROUP analytics_group; GRANT SELECT, UPDATE ON schema.table TO USER etl_user; """ content.write \ .format("com.databricks.spark.redshift") \ .option("aws_iam_role", role_arn) \ .option("url", host) \ .option("user", user) \ .option("password", pass) \ .option("dbtable", "schema.table") \ .option("tempdir", aws_bucket_name) \ .option("postactions", restore_permission_sql) \ .mode("overwrite") \ .save()如果不想手动维护赋权清单,可以提前查询Redshift系统表
information_schema.table_privileges,拉取目标表的现有权限配置,动态拼接GRANT语句传入即可。方案3:临时表交换元数据(大表高性能场景)
针对数据量较大的表,可以先将数据写入同名临时表,写入完成后执行Redshift原生的ALTER TABLE schema.table SWAP WITH schema.table_temp命令交换两张表的元数据,最后删除临时表。该方式写入性能远高于全量覆写,也可以在交换完成后灵活执行权限配置逻辑,不会出现权限丢失问题。
内容的提问来源于stack exchange,提问作者Loren

