Azure SQL Server单连接并发查询报错:aioodbc遇HY000驱动错误
单连接并发查询Azure SQL Server的问题解答
问题还原
使用aioodbc客户端连接Azure SQL Server时,通过单个连接的cursor并发执行查询,抛出错误:
'HY000', 'The driver did not supply an error!'
但将查询改为逐个串行执行时运行正常,并发执行的示例代码如下:
output1, output2 = await asyncio.gather( execute_fn1(cur, sql1), execute_fn2(cur, sql2) )
核心结论
ODBC不支持通过单个连接并行执行查询。
ODBC连接及其对应的cursor是协程/线程不安全的,同一时间只能处理一个数据库请求。当用asyncio.gather同时调用同一个cursor执行多个查询时,会打乱连接内部的状态管理逻辑,导致驱动抛出无明确信息的错误。
解决方案
1. 为每个并发任务创建独立连接
这是最推荐的方案,每个并发任务使用自己的数据库连接和cursor,避免资源竞争:
async def get_db_connection(): # 替换为你的数据库连接参数 conn = await aioodbc.connect( dsn="your_dsn", user="username", password="password", database="db_name" ) return conn async def execute_fn1(sql): async with await get_db_connection() as conn: async with conn.cursor() as cur: await cur.execute(sql) result = await cur.fetchall() return result async def execute_fn2(sql): async with await get_db_connection() as conn: async with conn.cursor() as cur: await cur.execute(sql) result = await cur.fetchall() return result # 并发执行 output1, output2 = await asyncio.gather( execute_fn1(sql1), execute_fn2(sql2) )
2. 对单连接加锁(不推荐)
如果必须复用单个连接,可以通过加锁强制同一时间只有一个任务使用cursor,但这样会让查询变回串行执行,失去并发的意义:
import asyncio # 全局锁 lock = asyncio.Lock() async def execute_fn1(cur, sql): async with lock: await cur.execute(sql) result = await cur.fetchall() return result async def execute_fn2(cur, sql): async with lock: await cur.execute(sql) result = await cur.fetchall() return result
内容的提问来源于stack exchange,提问作者Shankar
相关产品推荐
相关产品推荐

