sql >> Databasteknik >  >> RDS >> Oracle

Dödläge i Oracle

Jag vill göra ett skript där orakelsessionerna som hamnar i ett dödläge dödas automatiskt

REDIGERA Förklarade på ett bättre sätt, korrigerade några meningar och lade till ett testfall för att visa dödlägesscenariot.

Varför vill du uppfinna hjulet igen? Oracle upptäcker ett dödläge automatiskt, kastar ORA-00060: deadlock detected while waiting for resource , och rullar tillbaka en av transaktionerna som var involverade i dödläget som Oracle bestämde som offer. De tidigare framgångsrika transaktionerna återställs inte. Även efter dödlägesfelet, om en commit utfärdas, kommer den tidigare framgångsrika transaktionen att begås. Vid denna tidpunkt kommer även den andra sessionens transaktion att lyckas och du kan göra en commit. Det finns inget som du uttryckligen behöver göra här. Blockerade låsningar rensas automatiskt -- du behöver aldrig rensa dem.

Vanligtvis tar Oracle en eller två sekunder för att upptäcka ett dödläge och kastar felet.

Du kan prova med ett enkelt testfall som visas här:Förstå Oracle Deadlock

Låt oss titta på ett testfall -

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

Notera tidpunkten för varje transaktion, jag har ställt in tid på timing för en bättre förståelse.

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

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;

Vid det här laget fortsätter SESSION 2 att vänta .

SESSION:1

12:16:15 SQL> UPDATE t_test SET col_1 = 8 WHERE col_2=4;

Vid det här laget, SESSION 2 är offer för dödläge, SESSION 1 väntar fortfarande.

Låt oss titta på sessionsdetaljerna från 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>

Så, v$session detaljer när de visas i SESSION 2 , det vill säga SID 14, säger att statusen är AKTIV .

Låt oss titta på sessionsdetaljerna från en annan session, låt oss kalla det SESSION 3 för sakens skull. Kom ihåg, SESSION 1 väntar fortfarande.

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>

Så för andra sessioner, SESSION 2 , dvs SID 14, är INAKTIV . SESSION 1 är fortfarande VÄNTAR med händelse enq: TX - row lock contention .

Låt oss begå SESSION 2 -

12:22:18 SQL> commit;

Commit complete.

Elapsed: 00:00:00.01
12:25:43 SQL>

Vid denna tidpunkt släpps låset för SESSION 1 , låt oss begå session 1 också -

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 visar SESSION 1 väntade så länge till SESSION 2 var begått.

För att sammanfatta, här är hela historien om 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>

För att sammanfatta, här är hela historien om 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>

Nu ska vi se vilken transaktion som faktiskt återställdes och vilken som genomfördes -

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>

Slutsats

Enligt min åsikt är det bästa sättet att känna till sessionsdetaljerna för ett dödläge att logga detaljerna så utförligt som möjligt. Annars är det en mardröm för en DBA att undersöka utan korrekt information loggad. För den delen skulle till och med en utvecklare tycka att det är en häftig uppgift att rätta till och fixa det faktiska designfelet om detaljerna om dödlägesfelet inte loggas utförligt. Och för att avsluta med ett enkelt uttalande:Ett dödläge beror på designfel, Oracle är bara offret och applikationen är boven. Deadlocks är skrämmande, men de påpekar designbristerna som måste åtgärdas förr eller senare.



  1. SQL Server Texttyp kontra varchar datatyp

  2. Hur man skapar en databas i SQL Server

  3. BIN_TO_NUM() Funktion i Oracle

  4. 13 bloggartiklar om bästa praxis och tips för databasdesign