JDBC取消Oracle存储过程调用

Posted

技术标签:

【中文标题】JDBC取消Oracle存储过程调用【英文标题】:JDBC cancel Oracle stored procedure call 【发布时间】:2015-04-20 11:19:44 【问题描述】:

我有一个非常复杂的 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 Enterprise Edition Release 11.2.0.4.0 - 64bit Production JDBC 驱动程序版本为 11.2.0.4.0

我们将不胜感激。

【问题讨论】:

我也有同样的问题。你找到解决办法了吗? 【参考方案1】:

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

即使您终止会话,它也不会立即终止。它只是有状态 KILLED 并且它会在它真正死亡之前回滚所有内容。

如果 v$undostat 中的“使用的撤消块”在增加,则会话正在“做某事”。如果它正在减少,则会话正在回滚并且您没有其他选择,然后等待它完成。

已编辑:在 OCI 中,OCIBreak 调用被实现为带外数据包。它使用 TCP 标头中的特殊字段。使用 tcpdump 可以轻松识别此类数据包。因此,即使您没有必要的权限。在数据库方面,您至少可以验证 Break 数据包已发送到数据库。

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

【讨论】:

以上是关于JDBC取消Oracle存储过程调用的主要内容,如果未能解决你的问题,请参考以下文章

带有 PL SQL 表类型参数的 Oracle 存储过程的 JDBC 调用

使用简单的 jdbc 调用将数组作为输入参数传递给 oracle 存储过程

在 Oracle JDBC 中是不是可以批量存储过程调用和检索 OUT 参数?

java调用Oracle中的存储过程与存储函数

JDBC:Oracle 存储过程返回嵌套表

JDBC调用存储过程的例子