セッション全体を強制終了せずに、Oracle10.2.0.4でユーザーのクエリを強制終了できるようにしたいと思います。これにより、クエリを終了できますが、そのユーザーをセッションからログアウトできないため、他のクエリを続行できます。これは可能ですか?それとも、セッションを強制終了するという鈍いハンマーが、クエリの実行を終了する唯一の方法ですか?
4 に答える
コツを見つけました。これでどれだけ安全に遊べるかはわかりませんが、機能します。Oracle イベント 10237 があり、これは「^C をシミュレートする (テスト用)」と説明されています。
中断するセッションの SID と SERIAL# が必要です。
SYS.DBMS_SYSTEM.SET_EV( sid , serial# , 10237, 1, '' ) を呼び出して、ターゲット セッションでイベントをアクティブにします。現在実行中のステートメントは中断する必要があります (「ORA-01013: ユーザーが現在の操作のキャンセルを要求しました」を受け取ります)。イベントが設定されている限り、セッションが実行を試みる以降のステートメントは、同じエラーですぐに終了します。
イベントを無効にするには、4 番目のパラメーターを「0」に設定して同じ呼び出しを行います。その後、セッションは再びステートメントを実行できるようになります。
ターゲットセッションは、イベントが設定されていることを検出する必要があることに注意してください。これには、何を行っているかによって、時間がかかる場合と発生しない場合があります。そのため、イベントのオンとオフをすばやく切り替えることはできません。オンにして、問題のステートメントが停止していることを確認してから、オフにする必要があります。
ここにいくつかのサンプルコードがあります。これは、適切に定義された置換変数「sid」と「serial」を使用して、SQLPlus で無名ブロックとして実行されることを意図しています。これらをパラメータとしてストアドプロシージャに変えることができます。
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または同等のものを介して)問合せを取り消すことができる必要があります。
それ以外の場合は、Resource Manager を使用するのが最適です (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/