2009-01-21 66 views

回答

15

我發現了一個竅門。我不知道這是如何安全的,但它確實有效。有一個Oracle事件10237,被描述爲「模擬^ C(用於測試目的)」。

您必須擁有要中斷的會話的SID和SERIAL#號。

呼叫SYS.DBMS_SYSTEM.SET_EV(SID串行#,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; 
+1

不錯的一個。但是,從該循環中退出的條件可能更穩健 - 例如如果會話的狀態變爲「KILLED」或「SNIPED」,並且也可能是自動超時。 – 2009-06-05 03:11:26

1

你可以看看資源限制:

「,如果用戶超過了調用級資源限制,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 
2

我懷疑這可能是可能的,因爲你可以在TOAD中做到這一點。查詢運行時,出現「取消」對話框,您可以點擊該對話框停止查詢。

它是如何實現的我不知道,但會非常感興趣的發現。

如果您使用的是java,那麼java.sql.Statement的cancel()方法應該這樣做。看到這裏的一些注意事項和限制......

http://download.oracle.com/docs/cd/B14117_01/java.101/b10979/tips.htm#BACDAICJ

+1

蟾蜍通過運行在第二屆查詢做到這一點;如果操作員取消查詢,則TOAD殺死第二個會話。 – 2011-04-19 01:47:37

1

理想情況下,用戶的應用程序應該有能力取消查詢(通過OCICancel或等效)。

否則,最好使用資源管理器(如果在Oracle EE上),則可以使用DBMS_RESOURCE_MANAGER.SWITCH_CONSUMER_GROUP_FOR_SESS將目標會話設置爲使用者組CANCEL_SQL。

另一個黑客取消其他場次查詢,這並不用sqlplus Windows客戶端會話的工作,雖然,將使用kill -URG(這是一個黑客,而不是日常使用)

緊急信號發送到Oracle進程

我已經寫爲什麼它在這裏工作:

http://blog.tanelpoder.com/2010/02/17/how-to-cancel-a-query-running-in-another-session/