如何让Azure Databricks输出底层SQLException而非通用异常信息?
解决ADF调用Databricks Notebook时无法获取Synapse底层导入错误的问题
问题背景
通过Azure Data Factory(ADF)调用Databricks Notebook向Azure Synapse导入数据时,Notebook运行失败后ADF仅返回通用错误:
com.databricks.spark.sqldw.SqlDWSideException: Azure Synapse Analytics failed to execute the JDBC query produced by the connector.
真正定位问题的Underlying SQLException(s)(如列非空校验失败、字符串截断等)仅存在于Databricks日志深层,无法在ADF的runError输出中体现,导致每日数千次生产运行的故障无法通过Azure Log Analytics批量识别,只能手动逐个排查。
解决方案:改进异常捕获逻辑,提取底层错误信息
PySpark中调用Synapse连接器抛出的异常实际是Py4JJavaError,其内部嵌套了Java端的SqlDWSideException及更底层的SQLException。我们需要递归提取异常链中的底层错误信息,并将其包含在抛出的异常消息中,让ADF能捕获到完整的错误详情。
步骤1:编写底层异常提取函数
定义函数遍历Java异常的cause链,拼接所有底层错误信息:
from py4j.protocol import Py4JJavaError def get_full_error_message(exc): error_msg = [] # 处理Py4JJavaError(PySpark调用Java代码抛出的异常) if isinstance(exc, Py4JJavaError): java_exc = exc.java_exception error_msg.append(str(java_exc)) # 递归获取底层异常 current_cause = java_exc.getCause() while current_cause is not None: error_msg.append(f"Underlying SQLException(s):\n - {str(current_cause)}") current_cause = current_cause.getCause() else: # 处理普通Python异常 error_msg.append(str(exc)) current_cause = exc.__cause__ while current_cause is not None: error_msg.append(f"Underlying Exception: {str(current_cause)}") current_cause = current_cause.__cause__ return "\n".join(error_msg)
步骤2:修改数据导入代码的异常捕获块
替换原有简单的异常抛出逻辑,使用上述函数提取完整错误信息后再抛出:
try: data.write.format('com.databricks.spark.sqldw') \ .option("url", connection_string) \ .option("dbTable", table) \ .option("driver", "com.microsoft.sqlserver.jdbc.SQLServerDriver") \ .option("tempDir", Connection.storageaccount_path + 'store/dataload') \ .save(mode="append") except Exception as e: full_error = get_full_error_message(e) # 抛出包含完整错误信息的异常,ADF会捕获该消息并显示在runError中 raise Exception(f"Data load failed for table: {table}\n{full_error}") from e
效果说明
修改后,ADF的runError将直接显示包含底层SQLException的完整错误信息,例如:
Data load failed for table: target_table com.databricks.spark.sqldw.SqlDWSideException: Azure Synapse Analytics failed to execute the JDBC query produced by the connector. Underlying SQLException(s): - com.microsoft.sqlserver.jdbc.SQLServerException: HdfsBridge::recordReaderFillBuffer - Unexpected error encountered filling record reader buffer: HadoopExecutionException: The column [4] is not nullable and also USE_DEFAULT_VALUE is false, thus empty input is not allowed. [ErrorCode = 107090] [SQLState = S0001]
此时可以通过Azure Log Analytics针对具体错误关键词(如ErrorCode = 107090、String or Binary would be truncated)批量筛选故障记录,大幅提升排查效率。
内容的提问来源于stack exchange,提问作者LearneR
相关产品推荐
相关产品推荐

