我希望能够在不终止整个会话的情况下终止 Oracle 10.2.0.4 中的用户查询。这将允许查询结束,但不会将该用户从他们的会话中注销,因此他们可以继续进行其他查询。这可能吗?或者是终止会话的钝锤是结束查询执行的唯一方法吗?
4 回答
我发现了一个窍门。我不知道这玩起来有多安全,但它确实有效。有一个 Oracle 事件 10237,它被描述为“模拟 ^C(用于测试目的)”。
您必须拥有要中断的会话的 SID 和 SERIAL#。
调用 SYS.DBMS_SYSTEM.SET_EV( sid , serial# , 10237, 1, '' ) 以激活目标会话中的事件。任何当前正在执行的语句都应该被中断(收到“ORA-01013:用户请求取消当前操作”)。只要设置了事件,会话尝试执行的任何进一步语句都将立即终止,并出现相同的错误。
要停用事件,请在第四个参数设置为“0”的情况下进行相同的调用。然后会话将能够再次执行语句。
请注意,目标会话必须检测到事件已设置,这可能需要时间,或者可能永远不会发生,具体取决于它正在做什么。因此,您不能只是快速打开和关闭事件。您需要将其打开,验证相关语句是否已停止,然后将其关闭。
这是一些示例代码。这意味着在 SQLPlus 中作为匿名块运行,并适当定义了替换变量“sid”和“serial”。您可以将其转换为以这些为参数的存储过程。
DECLARE
l_status v$session.status%TYPE;
BEGIN
dbms_system.set_ev( &sid, &serial, 10237, 1, '');
LOOP
SELECT status INTO l_status FROM v$session
WHERE sid = &sid and serial# = &serial;
EXIT WHEN l_status='INACTIVE';
END LOOP;
dbms_system.set_ev( &sid, &serial, 10237, 0, '');
END;
我怀疑这可能是可能的,因为您可以在 TOAD 中执行此操作。当查询正在运行时,会出现一个取消对话框,您可以点击它来停止查询。
我不知道它是如何实现的,但也很想知道。
如果您使用的是 java,则应该使用 java.sql.Statement cancel() 方法来执行此操作。有关一些注意事项和限制,请参见此处...
http://download.oracle.com/docs/cd/B14117_01/java.101/b10979/tips.htm#BACDAICJ
您可以查看资源限制:
“如果用户超过了调用级别的资源限制,那么 Oracle 会暂停该语句的处理,回滚该语句并返回一个错误。但是,当前事务的所有先前语句保持不变,并且用户的会话保持连接。 "
假设取消 SQL 的原因是资源限制,而不是更新错误的行集(例如)。我怀疑您将无法通过添加资源限制来影响当前正在运行的 SQL。
http://download.oracle.com/docs/cd/B19306_01/server.102/b14220/security.htm#i13767
http://download.oracle.com/docs/cd/B19306_01/server.102/b14231/dbrm.htm#i1010776
理想情况下,用户的应用程序应该能够取消查询(通过 OCICancel 或等效方法)。
否则,最好使用资源管理器(如果在 Oracle EE 上),您可以使用 DBMS_RESOURCE_MANAGER.SWITCH_CONSUMER_GROUP_FOR_SESS 将目标会话设置为消费者组 CANCEL_SQL。
取消其他会话查询的另一个技巧是使用 kill -URG 向 Oracle 进程发送紧急信号,但它不适用于 sqlplus Windows 客户端会话(这是一种技巧,不适合日常使用)
我写过它为什么在这里工作:
http://blog.tanelpoder.com/2010/02/17/how-to-cancel-a-query-running-in-another-session/