Je veux faire un script où les sessions oracle qui entrent dans une impasse sont tuées automatiquement
MODIFIER Mieux expliqué, corrigé quelques phrases et ajouté un scénario de test pour illustrer le scénario de blocage.
Pourquoi voulez-vous réinventer la roue ? Oracle détecte automatiquement un interblocage, lance ORA-00060: deadlock detected while waiting for resource
, et annule l'une des transactions impliquées dans l'impasse qu'Oracle a désignée comme victime. Les transactions réussies précédentes ne sont pas annulées. Même après l'erreur de blocage, si une validation est émise, la transaction réussie précédente sera validée. À ce stade, la transaction de l'autre session réussira également et vous pourrez émettre un commit. Il n'y a rien que vous devez faire explicitement ici. Les interblocages sont automatiquement supprimés :vous n'avez jamais besoin de effacer eux.
Habituellement, Oracle prend une seconde ou deux pour détecter un blocage et renvoie l'erreur.
Vous pouvez essayer avec un cas de test simple comme illustré ici :Understanding Oracle Deadlock
Regardons un cas de test -
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
Notez l'heure de chaque transaction, j'ai mis l'heure sur le timing pour une meilleure compréhension.
SÉANCE :1
12:16:06 SQL> UPDATE t_test SET col_1 = 5 WHERE col_2=2;
1 row updated.
Elapsed: 00:00:00.00
SÉANCE :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;
À ce stade, SESSION 2 continue d'attendre .
SÉANCE :1
12:16:15 SQL> UPDATE t_test SET col_1 = 8 WHERE col_2=4;
À ce stade, SESSION 2 est victime d'un blocage, SESSION 1 attend toujours.
Regardons les détails de la session de SESSION 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>
Donc, v$session
détails lorsqu'ils sont affichés dans la SESSION 2 , c'est-à-dire SID 14, indique que l'état est ACTIVE .
Examinons les détails de la session d'une autre session, appelons-la SESSION 3 pour le bien. N'oubliez pas, SESSION 1 attend toujours.
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>
Donc, pour les autres sessions, SESSION 2 , c'est-à-dire SID 14, est INACTIF . SÉANCE 1 est toujours EN ATTENTE avec événement enq: TX - row lock contention
.
Commençons la SESSION 2 -
12:22:18 SQL> commit;
Commit complete.
Elapsed: 00:00:00.01
12:25:43 SQL>
À ce stade, le verrou est libéré pour la SESSION 1 , commitons également la session 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
montre SESSION 1 attendait si longtemps jusqu'à la SESSION 2 a été commis.
Pour résumer, voici toute l'histoire de la session 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>
Pour résumer, voici toute l'histoire de la session 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>
Voyons maintenant quelle transaction a été annulée et laquelle a été validée -
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>
Conclusion
À mon avis, la meilleure façon de connaître les détails de session d'un blocage est de consigner les détails aussi détaillés que possible. Sinon, c'est un cauchemar pour un DBA d'enquêter sans les informations appropriées enregistrées. D'ailleurs, même un développeur trouverait que c'est une tâche herculéenne de rectifier et de corriger le défaut de conception réel si les détails de l'erreur de blocage ne sont pas consignés de manière détaillée. Et pour conclure avec une seule phrase, un blocage est dû à un défaut de conception, Oracle n'est que la victime et l'application est le coupable. Les blocages font peur, mais ils mettent en évidence les défauts de conception qui doivent être corrigés tôt ou tard.