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ć.