JDBC QueryTimeout 仅适用于某些供应商
Posted
技术标签:
【中文标题】JDBC QueryTimeout 仅适用于某些供应商【英文标题】:JDBC QueryTimeout only working for some vendors 【发布时间】:2015-12-29 20:27:35 【问题描述】:我正在尝试使用 JDBC 向我的系统添加查询超时。我正在使用 statement.setQueryTimeout 函数来执行此操作。我知道这个值是在我使用 connection.createStatement、prepareStatement 等创建的语句上设置的,因为我已经使用 statement.getQueryTimeout 检查了它。但是,当使用不同的数据库(mysql、mssql、oracle 和 db2)进行测试时,只有 mysql 可以正常运行,而其他所有数据库实际上都不会超时
知道是什么原因造成的吗?我不确定为什么一种设置可以在高水平上运行,而其他设置则不行,因为我使用的是标准提供的驱动程序
【问题讨论】:
该 VedorId 查询的问题与该 VendorId 相关,它返回超时错误,因为它在该时间段内没有得到任何结果 检查您使用的 Oracle JDBC 驱动程序的版本。对于 Oracle,至少在协议级别是可能的。在使用 OCI 时,您可以从任何线程使用 OCIBreak,而不管主线程对连接执行什么操作。 OCIBreak 将向服务器发送 OOB(带外)数据包以取消查询执行。通常,您需要等待一段时间,直到 OCI 功能在 JDBC 中也受到影响。在这种情况下,问题在于 JVM 本身不支持 OOB TCP 功能。 感谢您的信息,我一定会调查的; OCIBreak 可能是一个足够好的解决方法 @Madden OCIBreak 是来自 OCI(C) 客户端的函数。 PS:在 JDBC 驱动程序中也有方法“Cancel()”。此方法应与 OCIBreak 相同,并且也是线程安全的。但是 AFAIK 您应该使用名为 ojdbc7.jar(而不是 ojdbc6.jar)的驱动程序。请参阅文档docs.oracle.com/cd/E11882_01/java.112/e16548/… 主题:我刚刚检查了 Oracle JDBC 驱动程序版本 10g 和 11g 中 Statement.cancel() 实现的文档。 10g版本里面多了一句“In some circumstances, the server is hung, but JDBC does not receive an IOException. Statement.cancel() does not free the thread that initiated the Statement.execute(). Due to limitations in the Java thread API, there is no acceptable workaround.
”。在 11g 中,这句话被删除了。那么他们找到解决方法了吗?还是他们只是购买了 Java,因此删除了此投诉?
【参考方案1】:
可能是那些驱动程序还没有实现它(还没有?)。某些数据库服务器无法定义查询超时。一些数据库服务器可能支持查询取消,但这需要驱动程序本身跟踪并异步向服务器发送取消,这可能会或可能不会在服务器上及时处理(例如,因为数据库服务器无法处理直到查询完成,因为连接线程当前正在处理查询)。
理论上客户端可以“放弃”查询,但这通常意味着连接本身变得不可用,因为连接的服务器端仍在工作(或服务器返回的响应未处理)。
长话短说:这是一个难题,并非所有数据库都有足够的支持来支持此 JDBC 功能。
【讨论】:
当然,我的意思是我使用的数据库都说它们支持 JDBC::setQueryTimeout 作为标准。我认为您提到的线程问题值得调查;我之前所做的研究表明,MySQL 实现创建了一个超时线程,它有自己的连接并处理关闭查询本身,而其他供应商创建一个线程,它只是将消息发送回父级,然后父级必须处理它 @Madden 取消来自不同连接的请求是一种有趣的方法。它确实增加了一些复杂性,因为对于许多数据库服务器,“语句标识”是连接本地的而不是服务器全局的,更不用说每个连接需要两个连接的开销,或者共享“取消”连接的协调.也就是说,我知道例如 Oracle 很难取消语句,即使您使用可用的管理功能来执行所述取消;)以上是关于JDBC QueryTimeout 仅适用于某些供应商的主要内容,如果未能解决你的问题,请参考以下文章
Mysql JDBC-mysql-Driver queryTimeout分析