简体   繁体   English

JDBC取消Oracle存储过程调用

[英]JDBC cancel Oracle stored procedure call

I have a very complex oracle stored procedure that searches and retrieves some data. 我有一个非常复杂的oracle存储过程,可以搜索和检索一些数据。 The procedure returns an output parameter - an oracle cursor. 该过程返回一个输出参数 - 一个oracle游标。 I execute the procedure by JDBC: 我通过JDBC执行该过程:

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

The problem is, the queries can sometimes take quite long (few minutes) and i would like user to be able to cancel the query anytime by clicking button. 问题是,查询有时需要很长时间(几分钟),我希望用户能够通过单击按钮随时取消查询。 I have reference to stmt object, but unfortunatelly calling stmt.cancel() (from other thread) has NO EFFECT. 我引用了stmt对象,但不幸的是调用stmt.cancel()(来自其他线程)没有效果。

On the other hand when i change the CallableStatement sql to some query like: 另一方面,当我将CallableStatement sql更改为某些查询时:

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

i get "java.sql.SQLTimeoutException: ORA-01013: user requested cancel of current operation" after calling stmt.cancel() - so thats the right reaction. 我在调用stmt.cancel()之后得到“java.sql.SQLTimeoutException:ORA-01013:用户请求取消当前操作” - 这就是正确的反应。

Does that mean than i cannot cancel stored procedure call via jdbc, but only simple select statements? 这是否意味着我不能通过jdbc取消存储过程调用,但只有简单的select语句? Does anyone else had and resolved similar problem? 有没有其他人解决过类似的问题?

I guess i could cancel the query by oracle kill session, but i use connection pooling (jboss) and i have plenty of sessions for the same user existing. 我想我可以通过oracle kill session取消查询,但我使用连接池(jboss),我有足够的会话为同一个用户存在。

Database Product Version is Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production JDBC Driver Version is 11.2.0.4.0 数据库产品版本是Oracle Database 11g企业版版本11.2.0.4.0 - 64位生产JDBC驱动程序版本是11.2.0.4.0

any help will be appreciated. 任何帮助将不胜感激。

Is that procedure read-only or it writes some data? 该过程是只读还是写入一些数据? Try to trace that session on db level and look into the trace file. 尝试在db级别跟踪该会话并查看跟踪文件。 You can also check v$undostat(used undo blocks) for that particular session. 您还可以检查该特定会话的v $ undostat(使用的撤消块)。 The OCIBreak call does not rollback the session, but might rollback the statement which was interrupted. OCIBreak调用不会回滚会话,但可能会回滚被中断的语句。

Even if you kill the session it will not die immediately. 即使你杀了会话,它也不会立即死亡。 It just has status KILLED and it will rollback everything before it really dies. 它的状态为KILLED,它会在它真正死亡之前回滚所有内容。

If "used undo blocks" in v$undostat is increasing then the session is "doing something". 如果v $ undostat中的“used undo blocks”正在增加,那么会话就是“做某事”。 If it is decreasing, the session is rolling back and you have no other option then wait till it is done. 如果它正在减少,会话将回滚,您没有其他选择,然后等待它完成。

EDITED: In OCI the OCIBreak call is implemented as out-of-band packet. 编辑:在OCI中,OCIBreak调用是作为带外数据包实现的。 It uses a special field in TCP header. 它使用TCP标头中的特殊字段。 Such a packet can be identified easily by using tcpdump. 可以使用tcpdump轻松识别这样的数据包。 So even if you do not have necessary privs. 所以,即使你没有必要的权限。 on database side you can at least verify, that Break packet was sent to the database. 在数据库端,您至少可以验证,Break数据包是否已发送到数据库。

When you are 100% sure that the break was sent to the database, then you have to investigate on db server side. 当您100%确定中断已发送到数据库时,您必须在数据库服务器端进行调查。 I think that some DDL statements like "drop user cascade" can not be interrupted. 我认为像“drop user cascade”这样的DDL语句不能被中断。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM