Databricks写入Azure Synapse报StringIndexOutOfBoundsException错误
问题根因
java.lang.StringIndexOutOfBoundsException: String index out of range: 14是旧版com.databricks.spark.sqldw连接器的典型解析报错,核心原因是连接器拿到的JDBC连接字符串不符合预期,解析时取固定偏移位置的字符判断协议前缀时触发越界,高频触发场景如下:
- 你贴的代码里
url配置存在语法错误:占位符<the-rest-of-the-connection-string>前缺失左双引号,和后面的右引号不配对,导致Spark实际传入连接器的url值被截断,长度不足14个字符,直接触发越界 - 传入的连接字符串不是完整的专用SQL池JDBC格式,缺失协议头、1433端口、目标数据库名等必填字段,连接器无法正常解析
- 代码逻辑混用读写API:你贴的示例代码用的是读取逻辑
.load(),如果要执行写入操作需要调用.save(),虽然报错栈显示你调用了save方法,也要确认实际运行的代码没有把读写参数、方法搞混
连接器原生支持自动建表能力,不需要提前在Synapse侧建空表,只要账号权限足够即可正常使用该特性。
修复步骤
- 修正连接配置语法与格式
首先修复url参数的引号问题,填入完整的专用SQL池JDBC连接串,不要遗漏必填字段,写入逻辑的正确代码示例如下:
# 注意是write不是read,最后调用save() df.write \ .format("com.databricks.spark.sqldw") \ .option("url", "jdbc:sqlserver://<你的Synapse实例名>.sql.azuresynapse.net:1433;database=<你的专用SQL池数据库名>;user=<SQL认证用户名>;password=<SQL认证密码>;encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.sql.azuresynapse.net;loginTimeout=30;") \ .option("forwardSparkAzureStorageCredentials", "true") \ .option("dbTable", "dbo.<你的目标表名>") \ .option("tempDir", "wasbs://<你的容器名>@<你的存储账号名>.blob.core.windows.net/<临时目录路径>") \ .mode("append") # 全量覆盖表就替换为"overwrite",该模式会自动删表重建 .save()
- 校验权限配置
- 你使用的SQL认证账号,需要对目标数据库拥有CREATE TABLE、INSERT、SCHEMA修改权限,满足自动建表要求
- 临时目录所在的Blob存储账号,需要同时给Databricks集群、Synapse专用SQL池分配存储Blob数据贡献者权限,开了存储防火墙的话要放通两个服务的出口IP
- 版本兼容适配
如果你使用的是Databricks Runtime 10.0及以上版本,建议直接替换为Databricks内置的新版Synapse连接器,只需要把format参数里的com.databricks.spark.sqldw替换为com.databricks.spark.synapse即可,新版修复了旧版大量连接字符串解析、类型映射的bug,稳定性更好。
验证方法
改完配置后先构造极简测试DataFrame做验证,排除其他变量干扰:
test_df = spark.createDataFrame([(1,"test"),(2,"test2")], schema="id INT, name STRING") # 替换为上面的写入逻辑,把df换成test_df跑通后再换正式数据
如果还是报同类错误,先打印你代码里实际传入的url参数值,确认没有多余占位符、引号转义问题,字符串以jdbc:sqlserver://开头,包含所有必填连接参数即可。
内容的提问来源于stack exchange,提问作者gglima
相关产品推荐
相关产品推荐

