Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Zakleszczenia w Oracle

Chcę stworzyć skrypt, w którym sesje oracle, które przejdą w impas, zostaną automatycznie zabite

EDYTUJ Wyjaśniono w lepszy sposób, poprawiono kilka zdań i dodano przypadek testowy, aby zademonstrować scenariusz impasu.

Dlaczego chcesz ponownie wynaleźć koło? Oracle automatycznie wykrywa zakleszczenie, zgłasza ORA-00060: deadlock detected while waiting for resource i wycofuje jedną z transakcji związanych z impasem, który Oracle wybrał jako ofiarę. Poprzednie pomyślne transakcje nie są wycofywane. Nawet po błędzie zakleszczenia, jeśli zostanie wydane zatwierdzenie, zostanie zatwierdzona poprzednia pomyślna transakcja. W tej chwili transakcja drugiej sesji również się powiedzie i możesz wydać zatwierdzenie. Nie musisz tutaj nic wyraźnie robić. Zakleszczenia są automatycznie usuwane – nigdy nie musisz czyścić ich.

Zwykle Oracle zajmuje sekundę lub dwie, aby wykryć zakleszczenie i zgłasza błąd.

Możesz spróbować za pomocą prostego przypadku testowego, jak pokazano tutaj:Zrozumienie impasu Oracle

Spójrzmy na przypadek testowy -

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

Zwróć uwagę na czas każdej transakcji, dla lepszego zrozumienia ustaliłem czas.

SESJA:1

12:16:06 SQL> UPDATE t_test SET col_1 = 5 WHERE col_2=2;

1 row updated.

Elapsed: 00:00:00.00

SESJA: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;

W tym momencie SESJA 2 nadal czeka .

SESJA:1

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

W tym momencie SESJA 2 jest ofiarą impasu, SESJA 1 wciąż czeka.

Przyjrzyjmy się szczegółom sesji z SESJI 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>

A więc v$session szczegóły podczas przeglądania w SESJI 2 , czyli SID 14, mówi, że stan to AKTYWNY .

Przyjrzyjmy się szczegółom sesji z innej sesji, nazwijmy to SESJĄ 3 ze względu na. Pamiętaj, SESJA 1 wciąż czeka.

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>

Tak więc w przypadku innych sesji SESJA 2 , czyli SID 14, jest NIEAKTYWNY . SESJA 1 nadal CZEKA ze zdarzeniem enq: TX - row lock contention .

Zatwierdźmy sesję 2 -

12:22:18 SQL> commit;

Commit complete.

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

W tym momencie blokada zostaje zwolniona na SESJĘ 1 , zatwierdźmy również sesję 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 pokazuje SESJĘ 1 tak długo czekałem na sesję 2 zostało popełnione.

Podsumowując, oto cała historia sesji 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>

Podsumowując, oto cała historia sesji 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>

Zobaczmy teraz, która transakcja została faktycznie wycofana, a która zatwierdzona -

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>

Wniosek

Moim zdaniem najlepszym sposobem poznania szczegółów sesji impasu jest rejestrowanie szczegółów tak szczegółowo, jak to możliwe. W przeciwnym razie prowadzenie dochodzenia przez administratora bez rejestrowania odpowiednich informacji jest koszmarem. Jeśli o to chodzi, nawet programista uznałby, że naprawienie i naprawienie rzeczywistej wady projektu jest herkulesowym zadaniem, jeśli szczegóły błędu impasu nie są szczegółowo rejestrowane. I na zakończenie jednolinijkowym stwierdzeniem:Impas wynika z wady projektu, Oracle jest tylko ofiarą, a aplikacja jest winowajcą. Zakleszczenia są przerażające, ale wskazują na wady konstrukcyjne, które prędzej czy później należy naprawić.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Różnica między VARCHAR2 (10 CHAR) a NVARCHAR2 (10)

  2. Czy istnieje pragma PL/SQL podobna do DETERMINISTIC, ale dla zakresu pojedynczego SQL SELECT?

  3. Oracle PL/SQL:Przykład UTL_FILE.FCOPY

  4. Czy SQLDeveloper obsługuje wykonywanie skryptów?

  5. Test wydajności i dostrajania Oracle