如何为OdbcConnection的QueryAsync正确设置查询超时?
解决高并发下Sybase ODBC连接及查询超时问题
报错信息
ERROR [08003] [Sybase][ODBC Driver]Connection not open: not connected to SQL database
ERROR [08001] [Sybase][ODBC Driver]Unable to connect to database server
问题核心分析
OdbcConnection.ConnectionTimeout仅控制建立数据库连接的超时时间,和查询执行阶段的超时无关——这就是你设置后无效的原因。高并发场景下出现这类错误,大概率是连接池耗尽、查询执行过久导致连接被服务器主动断开,或是连接请求排队超时。
针对性解决方案
1. 设置查询执行超时时间
使用commandTimeout参数(对应Dapper查询的执行超时),直接在QueryAsync中指定:
using (OdbcConnection db = new OdbcConnection(DSNs["kxp"])) { db.ConnectionTimeout = dbConnectionTimeout; // 保留连接超时设置 // 新增查询超时配置(示例设为30秒,可根据业务调整) IEnumerable<KxpWarehouse> productions = (await db.QueryAsync<KXPWarehous>( stmt, new { queryDate }, commandTimeout: 30 )) .Select(idl => new KxpWarehouse { name = idl.name, stamp = idl.stamp, queue1 = idl.queue1, queue2 = idl.queue2, arrived = idl.arrived, remains = idl.remains, total = idl.total, }).ToList(); // 编码转换逻辑保持不变 List<KxpWarehouse> kxpWarehouseInfo = new List<KxpWarehouse>(); foreach (var item in productions) { byte[] bytes = Encoding.GetEncoding(1251).GetBytes(item.name); item.name = Encoding.GetEncoding(866).GetString(bytes); bytes = Encoding.GetEncoding(1251).GetBytes(item.stamp); item.stamp = Encoding.GetEncoding(866).GetString(bytes); kxpWarehouseInfo.Add(item); } return kxpWarehouseInfo; }
2. 优化连接池配置
高并发下连接池资源不足会导致连接请求排队超时,可在连接字符串中调整池参数:
Max Pool Size: 调高最大连接数(默认100,可根据服务器承载能力调整,比如设为200)Min Pool Size: 设置最小空闲连接数,避免频繁创建销毁连接Connection Lifetime: 超过该时间的连接会被自动销毁重建,防止长时间连接失效
示例连接字符串修改:
DSN=kxp;Max Pool Size=200;Min Pool Size=10;Connection Lifetime=300;
3. 优化查询性能
查询执行过久是高并发下连接被断开的常见诱因,建议:
- 检查
stmt对应的SQL语句,确保queryDate字段有索引 - 只返回业务需要的字段,减少数据传输量
- 若结果集过大,考虑分页查询
4. 显式管理连接状态
虽然Dapper会自动处理连接的打开/关闭,但高并发下显式控制连接状态可提升稳定性:
using (OdbcConnection db = new OdbcConnection(DSNs["kxp"])) { db.ConnectionTimeout = dbConnectionTimeout; await db.OpenAsync(); // 显式打开连接 var productions = await db.QueryAsync<KXPWarehous>( stmt, new { queryDate }, commandTimeout: 30 ); // 后续逻辑不变 }
内容的提问来源于stack exchange,提问作者Quribe
相关产品推荐
相关产品推荐

