java - JDBC取消Oracle存储过程调用

标签 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: 用户请求取消当前操作”——所以这是正确的 react 。

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

我想我可以通过 oracle kill session 取消查询,但我使用连接池 (jboss) 并且我有大量现有的同一个用户的 session 。

数据库产品版本为 Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production JDBC驱动版本为11.2.0.4.0

我们将不胜感激。

最佳答案

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

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

如果 v$undostat 中的“已使用的撤消 block ”在增加,那么 session 正在“做某事”。如果它正在减少,则 session 正在回滚,您别无选择,只能等到它完成。

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

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

关于java - JDBC取消Oracle存储过程调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28600858/

相关文章:

java - 如何在 Java 中正确处理定时器?

java - 动态模块 : How to add auto increment numbers to key field while adding record to table

Oracle 事务读取一致性?

linux - Nodejs模块oracle找不到LD_LIBRARY_PATH

java - JPA + StoredProcedureCall + 对象类型 IN 参数

java - 如何向注入(inject)的类成员提供模拟实例

java - 约会和行项目

oracle - 在Oracle中生成大小写字母数字随机字符串

mysql - 如何在 Mysql 存储过程中包含一个 .sh(脚本)文件?

php - Doctrine DBAL 对存储过程的支持