从Databricks将Delta表写入Azure Synapse专用SQL池时遭遇Base64格式无效错误
我帮你分析下这个问题,这个The input is not a valid Base-64 string错误(ErrorCode 110813)在Databricks写入Synapse专用池时很常见——既然你已经确认数据能成功复制到ADLS暂存区,说明问题出在Synapse访问暂存区的凭证解析环节,或者路径/配置有格式错误。结合你的代码,给你几个具体的排查和解决步骤:
1. 检查ADLS暂存路径的格式
首先确认你的adls变量是完整的ABFS格式,不能有拼写错误、多余字符或者格式缺失:
# 正确格式示例 adls = "abfss://your-container@your-storage-account.dfs.core.windows.net/synapse-temp-folder"
注意:
- 必须使用
abfss://协议(而非wasbs://或其他) - 末尾不要加多余的斜杠
/ - 存储账户名和容器名必须完全匹配
2. 验证Spark集群对ADLS的访问权限
你设置了forward_spark_azure_storage_credentials="True",这个选项依赖Databricks集群的ADLS访问凭证(服务主体、MSI或存储密钥)。先测试集群能不能正常读写该暂存路径:
# 测试ADLS读写 test_df = spark.range(10) test_df.write.mode("overwrite").parquet(f"{adls}/test-check") test_read = spark.read.parquet(f"{adls}/test-check") print(f"测试读取行数:{test_read.count()}")
如果这个测试失败,说明集群的ADLS凭证配置有问题,需要先修复(比如检查服务主体的权限、密钥是否正确、MSI是否启用),再尝试写入Synapse。
3. 修正JDBC URL的配置
你的sqlDwUrlSmall缺少必要的JDBC连接选项,建议补充加密和证书验证的正确配置(注意把trustServerCertificate设为false,避免证书验证漏洞):
sqlDwUrlSmall = f"jdbc:sqlserver://{dwServer}:{dwJdbcPort};database={dwDatabase};user={dwUser};password={dwPass};encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30;"
4. 尝试改用SAS令牌访问暂存区
如果凭证传递的方式(forward_spark_azure_storage_credentials)一直出问题,可以跳过这个选项,直接用SAS令牌让Synapse访问ADLS暂存区:
# 替换成你的ADLS容器SAS令牌(不要包含开头的?) sas_token = "sv=2022-11-02&ss=bfqt&srt=sco&sp=rwdlacupiytfx&se=2024-12-31T23:59:59Z&st=2024-01-01T00:00:00Z&spr=https&sig=XXXXXXX" tempdir_with_sas = f"{adls}?{sas_token}" # 写入Synapse的代码(去掉forward_credentials选项) (df .write .format("com.databricks.spark.sqldw") .option("url", sqlDwUrlSmall) .option("dbtable", "Product_Dim") .option("tempdir", tempdir_with_sas) .mode("overwrite") .save())
这种方式不需要依赖Spark的凭证,直接通过SAS令牌授权Synapse访问暂存区,能绕过Base64凭证解析的问题。
5. 排查DataFrame的字段名(可选)
虽然可能性较低,但如果你的DataFrame字段名包含Synapse不支持的特殊字符(比如空格、-、@),也可能导致解析异常,可以先重命名字段:
# 把所有字段名替换为下划线格式 df = df.toDF(*[col_name.replace(" ", "_").replace("-", "_").replace("@", "_") for col_name in df.columns])
按照这个顺序排查,基本能解决这个Base64无效的问题。
内容的提问来源于stack exchange,提问作者Rahul Yadav

