Oracle
 sql >> Base de données >  >> RDS >> Oracle

Blocages dans Oracle

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.