デッドロックに陥ったオラクルセッションが自動的に強制終了されるスクリプトを作成したい
編集 より良い方法で説明し、いくつかの文を修正し、デッドロックシナリオを示すためのテストケースを追加しました。
なぜあなたは車輪の再発明をしたいのですか? Oracleはデッドロックを自動的に検出し、ORA-00060: deadlock detected while waiting for resource
をスローします。 、およびOracleが被害者として決定したデッドロックに関連するトランザクションの1つをロールバックします。以前に成功したトランザクションはロールバックされません。デッドロックエラーが発生した後でも、コミットが発行されると、前に成功したトランザクションがコミットされます。このとき、他のセッションのトランザクションも成功し、コミットを発行できます。 ここで明示的に行う必要があることは何もありません。デッドロックは自動的にクリアされます。クリアする必要はありません。 それら。
通常、Oracleはデッドロックを検出してエラーをスローするのに1〜2秒かかります。
ここに示されているように、簡単なテストケースで試すことができます:OracleDeadlockについて
テストケースを見てみましょう-
SQL> CREATE TABLE t_test(col_1 NUMBER, col_2 NUMBER);
Table created
SQL> INSERT INTO t_test VALUES(1,2);
1 row inserted
SQL> INSERT INTO t_test VALUES(3,4);
1 row inserted
SQL> COMMIT;
Commit complete
SQL> SELECT * FROM t_test;
COL_1 COL_2
---------- ----------
1 2
3 4
各トランザクションの時刻に注意してください。理解を深めるために、タイミングをオンに設定しました。
セッション:1
12:16:06 SQL> UPDATE t_test SET col_1 = 5 WHERE col_2=2;
1 row updated.
Elapsed: 00:00:00.00
セッション:2
12:16:04 SQL> UPDATE t_test SET col_1 = 6 WHERE col_2=4;
1 row updated.
Elapsed: 00:00:00.00
12:16:31 SQL> UPDATE t_test SET col_1 = 7 WHERE col_2=2;
この時点で、セッション2は待機し続けます 。
セッション:1
12:16:15 SQL> UPDATE t_test SET col_1 = 8 WHERE col_2=4;
この時点で、セッション2 デッドロックの犠牲者です、セッション1 まだ待っています。
セッション2のセッションの詳細を見てみましょう -
12:22:15 SQL> select sid,status,program,sql_id, state, wait_class, blocking_session_status, event from v$session where schemaname='LALIT' and program='sqlplus.exe';
SID STATUS PROGRAM SQL_ID STATE WAIT_CLASS BLOCKING_SE EVENT
---------- -------- --------------- ------------- ------------------- --------------- ----------- ----------------------------------------------------------------
14 ACTIVE sqlplus.exe 60qmqpmbmyhxn WAITED SHORT TIME Network NOT IN WAIT SQL*Net message to client
134 ACTIVE sqlplus.exe 5x0zg4qwus29v WAITING Application VALID enq: TX - row lock contention
Elapsed: 00:00:00.00
12:22:18 SQL>
したがって、v$session
セッション2で表示した場合の詳細 、つまりSID 14は、ステータスがアクティブであることを示しています 。
別のセッションのセッションの詳細を見てみましょう。セッション3と呼びましょう。 のための。 セッション1を忘れないでください まだ待っています。
SQL> set time on timing on
12:24:41 SQL> select sid,status,program,sql_id, state, wait_class, blocking_session_status, event from v$session where schemaname='LALIT' and program='sqlplus.exe'
SID STATUS PROGRAM SQL_ID STATE WAIT_CLASS BLOCKING_SE EVENT
---------- -------- --------------- ------------- ------------------- ---------- ----------- ------------------------------
13 ACTIVE sqlplus.exe 60qmqpmbmyhxn WAITED SHORT TIME Network NOT IN WAIT SQL*Net message to client
14 INACTIVE sqlplus.exe WAITING Idle NO HOLDER SQL*Net message from client
134 ACTIVE sqlplus.exe 5x0zg4qwus29v WAITING Applicatio VALID enq: TX - row lock contention
n
Elapsed: 00:00:00.01
12:24:44 SQL>
したがって、他のセッションについては、セッション2 、つまりSID14は非アクティブです 。 セッション1 まだ待機中 イベントenq: TX - row lock contention
。
セッション2をコミットしましょう -
12:22:18 SQL> commit;
Commit complete.
Elapsed: 00:00:00.01
12:25:43 SQL>
この時点で、セッション1のロックが解除されます。 、セッション1もコミットしましょう-
12:16:15 SQL> UPDATE t_test SET col_1 = 8 WHERE col_2=4;
1 row updated.
Elapsed: 00:08:27.29
12:25:43 SQL> commit;
Commit complete.
Elapsed: 00:00:00.00
12:26:26 SQL>
Elapsed: 00:08:27.29
セッション1を表示します セッション2までずっと待っていました コミットされました。
要約すると、これがセッション1の全体像です -
12:16:06 SQL> UPDATE t_test SET col_1 = 5 WHERE col_2=2;
1 row updated.
Elapsed: 00:00:00.00
12:16:15 SQL> UPDATE t_test SET col_1 = 8 WHERE col_2=4;
1 row updated.
Elapsed: 00:08:27.29
12:25:43 SQL> commit;
Commit complete.
Elapsed: 00:00:00.00
12:26:26 SQL>
要約すると、これがセッション2の全体像です -
12:16:04 SQL> UPDATE t_test SET col_1 = 6 WHERE col_2=4;
1 row updated.
Elapsed: 00:00:00.00
12:16:31 SQL> UPDATE t_test SET col_1 = 7 WHERE col_2=2;
UPDATE t_test SET col_1 = 7 WHERE col_2=2
*
ERROR at line 1:
ORA-00060: deadlock detected while waiting for resource
Elapsed: 00:00:24.47
12:22:15 SQL> select sid,status,program,sql_id, state, wait_class, blocking_session_status, event from v$session where schemaname='LALIT' and program='sqlplus.exe';
SID STATUS PROGRAM SQL_ID STATE WAIT_CLASS BLOCKING_SE EVENT
---------- -------- --------------- ------------- ------------------- --------------- ----------- ----------------------------------------------------------------
14 ACTIVE sqlplus.exe 60qmqpmbmyhxn WAITED SHORT TIME Network NOT IN WAIT SQL*Net message to client
134 ACTIVE sqlplus.exe 5x0zg4qwus29v WAITING Application VALID enq: TX - row lock contention
Elapsed: 00:00:00.00
12:22:18 SQL> commit;
Commit complete.
Elapsed: 00:00:00.01
12:25:43 SQL>
それでは、実際にロールバックされたトランザクションとコミットされたトランザクションを見てみましょう。 -
12:25:43 SQL> select * from t_test;
COL_1 COL_2
---------- ----------
5 2
8 4
Elapsed: 00:00:00.00
12:30:36 SQL>
結論
私の意見では、デッドロックのセッションの詳細を知る最良の方法は、可能な限り詳細をログに記録することです。そうでなければ、適切な情報を記録せずにDBAが調査するのは悪夢です。さらに言えば、デッドロックエラーの詳細が詳細に記録されていない場合、開発者でさえ、実際の設計上の欠陥を修正して修正するのは非常に困難な作業であることがわかります。そして、ワンライナーステートメントで締めくくります。デッドロックは設計上の欠陥によるものです。 Oracleは被害者であり、アプリケーションが原因です。デッドロックは恐ろしいものですが、遅かれ早かれ修正しなければならない設計上の欠陥を指摘しています。