JDBC取消Oracle存储过程调用

时间:2015-02-19 07:36:04

标签: java oracle stored-procedures jdbc oracle11g

我有一个非常复杂的oracle存储过程,可以搜索和检索一些数据。该过程返回一个输出参数 - 一个oracle游标。 我通过JDBC执行该过程:

CallableStatement stmt = conn.prepareCall("{call myprocedure(?,?,?,?}");

问题是,查询有时需要很长时间(几分钟),我希望用户可以通过单击按钮随时取消查询。 我引用了stmt对象,但不幸的是调用stmt.cancel()(来自其他线程)没有效果。

另一方面,当我将CallableStatement sql更改为某些查询时:

CallableStatement stmt = conn.prepareCall("select * from all_objects");

我在调用stmt.cancel()之后得到“java.sql.SQLTimeoutException:ORA-01013:用户请求取消当前操作” - 这是正确的反应。

这是否意味着我不能通过jdbc取消存储过程调用,而只是简单的select语句? 有没有其他人解决过类似的问题?

我想我可以通过oracle kill session取消查询,但是我使用连接池(jboss),并且我有足够的会话用于同一个用户。

数据库产品版本是Oracle Database 11g企业版版本11.2.0.4.0 - 64位生产 JDBC驱动程序版本为11.2.0.4.0

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

该程序是只读还是写入一些数据?尝试在db级别跟踪该会话并查看跟踪文件。您还可以检查该特定会话的v $ undostat(使用的撤消块)。 OCIBreak调用不会回滚会话,但可能会回滚被中断的语句。

即使你杀了会话,它也不会立即死亡。它的状态为KILLED,它会在它真正死亡之前回滚所有内容。

如果v $ undostat中的“used undo blocks”正在增加,那么会话就是“做某事”。如果它正在减少,会话将回滚,你没有其他选择,然后等待它完成。

EDITED:在OCI中,OCIBreak调用是作为带外数据包实现的。它使用TCP标头中的特殊字段。可以使用tcpdump轻松识别这样的数据包。所以,即使你没有必要的权限。在数据库方面,您至少可以验证,Break数据包是否已发送到数据库。

当您100%确定中断已发送到数据库时,您必须在数据库服务器端进行调查。我认为像“drop user cascade”这样的DDL语句不能被中断。