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

Redshift ODBC 2.x适配pyodbc超4KB大字段读取问题咨询

Redshift ODBC 2.x 适配pyodbc读取超4KB数据的问题修复方案

问题重现代码

import pyodbc    
query = 'SELECT REPEAT(\'a\', 5000)'  # 修正原代码中statement变量未定义的问题
cnxn = pyodbc.connect('Driver={Amazon Redshift ODBC Driver (x64)}; Server=srv.amazonaws.com...')
cursor = cnxn.cursor()
cursor.execute(query)
val = cursor.fetchall()[0][0]

问题现象

执行上述代码后,val的值在2046字符后出现损坏,无法完整获取5000字符的完整数据。

问题分析

查看pyodbc与ODBC规范及源码后发现:

  • pyodbc默认初始分配4KB缓冲区调用SQLGetData,Redshift ODBC驱动填充4KB数据后返回实际数据总大小(如5000字节)。
  • pyodbc随后重新分配对应大小的缓冲区,设置已使用字节数cbUsed为4KB,再次调用SQLGetData,期望驱动从上次的偏移位置续写剩余数据。
  • 但Redshift ODBC 2.x驱动未实现状态维护逻辑,无法记录已读取的位置,每次调用SQLGetData都会从头写入数据,导致后续数据覆盖或损坏。

核心问题解答

1. ODBC是否需要保持状态?

根据ODBC官方规范,支持分段读取大字段的驱动必须维护状态。当应用程序多次调用SQLGetData读取同一字段时,驱动需要记录当前已读取的偏移量,后续调用时从该位置继续返回剩余数据。Redshift ODBC 2.x的行为不符合这一规范,属于驱动实现缺陷。

2. 如何确定需写入的数据块?

对于符合规范的ODBC驱动:

  • 首次调用SQLGetData时,驱动返回字段总长度,同时将缓冲区填满至最大容量(如4KB)。
  • 后续调用时,驱动根据已维护的读取状态,计算剩余未读取的数据长度,将剩余数据写入新缓冲区的对应偏移位置,直到数据全部读取完成。
  • 若驱动不支持状态维护,只能通过调整应用层逻辑或驱动配置来规避问题。

可行修复方案

  • 方案一:升级Redshift ODBC驱动
    Amazon后续发布的Redshift ODBC 3.x版本已修复该分段读取的状态维护问题,升级至最新版驱动是最彻底的解决方案。
  • 方案二:增大pyodbc初始缓冲区
    修改pyodbc的默认初始缓冲区大小,使其超过你的最大字段长度(比如设置为10KB)。可以通过连接字符串参数MaxLongVarcharSize(部分驱动支持)调整,或修改pyodbc源码中默认缓冲区配置后重新编译。
  • 方案三:应用层手动拆分读取
    若无法升级驱动,可在SQL查询中手动将大字段拆分为多个小片段读取,再在Python中拼接:
    SELECT 
      SUBSTRING(long_column, 1, 4000) AS part1,
      SUBSTRING(long_column, 4001, 5000) AS part2 
    FROM your_table;
    
    然后在代码中执行full_data = part1 + part2得到完整内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 19:52:42