You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

UCanAccess读取Access表重复将列名作为数据返回如何解决

异常根因

该异常是UCanAccess 5.0.1版本已知游标初始化缺陷与Spark 3.1.2 JDBC数据源默认读取逻辑共同触发的兼容问题:
Spark JDBC读取表时会在同一个JDBC连接上先后执行两次操作:第一次查询表元数据获取列结构,第二次拉取全表数据统计行数、返回记录。UCanAccess 5.0.1在同连接连续执行同表查询时,结果集游标不会自动重置到真实数据行的起始位置,会停留在驱动内部缓存的列名元数据行,后续遍历行时持续返回列名值;由于驱动内部缓存的真实数据行数统计正常,因此df.count()会返回正确的记录数,printSchema()也能正常识别列结构,但实际读取的行内容全部为列名。
Databricks 9.1LTS默认开启JDBC连接复用,不会为元数据查询和数据查询单独创建新连接,刚好触发该缺陷。

排查思路
  • 先排除源文件问题:将Access文件下载到本地,用本地Access客户端打开,确认Table1内存储的真实数据和预期一致,没有误把列名存成数据行、也没有错误设置"第一行作为列标题/数据"的表属性。
  • 验证驱动兼容问题:在同集群用Scala/Java原生JDBC代码写测试逻辑,在单个UCanAccess连接上连续执行两次SELECT * FROM Table1,如果第二次查询返回的内容全部是列名,即可确认是驱动本身的游标bug。
  • 参数调整验证:在JDBC URL中逐个追加UCanAccess官方提供的缓存、连接控制参数,测试数据读取是否恢复正常,定位触发bug的配置项。
  • 版本对比验证:替换不同版本的UCanAccess驱动(比如4.0.4、5.0.2),测试相同读取代码的返回结果,确认版本兼容问题。
可行解决方案

按落地成本从低到高排序:

  1. 调整JDBC连接URL参数,绕过bug
    不需要更换驱动,直接在原有URL后追加参数,关闭驱动内存缓存和连接复用,强制每次查询重置游标:
    url = "jdbc:ucanaccess:///dbfs/mnt/internal/Temporal/Database1.accdb;memory=false;openExclusive=false;ignoreCase=true"
    
    同时读取时指定子查询代替直接读表,避免Spark拆分两次查询触发游标异常:
    df = spark.read.jdbc(url=url, table="(SELECT ID, Field1, Field2 FROM Table1) AS query_res", properties=connectionProperties)
    
  2. 更换UCanAccess驱动版本
    该游标bug在UCanAccess 5.0.2及以上版本已经修复,也可以选择兼容性更稳定的4.0.4版本,上传到Databricks集群的依赖库中替换原有5.0.1版本即可,注意要同步上传驱动对应版本的配套依赖(jackcess、hsqldb、commons-logging等),避免类冲突。
  3. 调整Spark JDBC读取配置
    关闭Spark的JDBC谓词下推和schema自动推断,手动指定schema,避免Spark单独发起元数据查询:
    from pyspark.sql.types import StructType, StructField, StringType
    # 手动定义表结构
    custom_schema = StructType([
        StructField("ID", StringType(), True),
        StructField("Field1", StringType(), True),
        StructField("Field2", StringType(), True)
    ])
    df = spark.read.format("jdbc") \
        .option("url", url) \
        .option("dbtable", "Table1") \
        .option("driver", "net.ucanaccess.jdbc.UcanaccessDriver") \
        .option("pushDownPredicate", "false") \
        .option("schema", custom_schema.json()) \
        .load()
    

内容的提问来源于stack exchange,提问作者Alex Wong

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 05:27:13