Искам да направя скрипт, при който сесиите на оракула, които влизат в безизходица, се убиват автоматично
РЕДАКТИРАНЕ Обяснено по по-добър начин, коригирано няколко изречения и добавен тестов случай, за да се демонстрира сценарий в безизходица.
Защо искате да изобретите колелото? Oracle открива автоматично блокиране, хвърля ORA-00060: deadlock detected while waiting for resource
, и отменя една от транзакциите, включени в задънената улица, която Oracle реши като жертва. Предишните успешни транзакции не се връщат назад. Дори след грешката в застой, ако бъде издаден комит, предишната успешна транзакция ще бъде завършена. По това време транзакцията на другата сесия също ще бъде успешна и можете да издадете ангажимент. Няма нищо, което трябва да правите изрично тук. Блокировките се изчистват автоматично – никога не е необходимо да изчиствате тях.
Обикновено Oracle отнема секунда или две, за да открие застой и извежда грешката.
Можете да опитате с прост тестов случай, както е показано тук:Разбиране на Oracle Deadlock
Нека да разгледаме тестов случай -
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
Обърнете внимание на времето на всяка транзакция, задал съм време за време за по-добро разбиране.
СЕСИЯ:1
12:16:06 SQL> UPDATE t_test SET col_1 = 5 WHERE col_2=2;
1 row updated.
Elapsed: 00:00:00.00
СЕСИЯ: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;
В този момент СЕСИЯ 2 продължава да чака .
СЕСИЯ:1
12:16:15 SQL> UPDATE t_test SET col_1 = 8 WHERE col_2=4;
В този момент СЕСИЯ 2 е жертва на безизходица, СЕСИЯ 1 все още чака.
Нека разгледаме подробностите за сесията от СЕСИЯ 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>
И така, v$session
подробности при преглед в СЕСИЯ 2 , т.е. SID 14, казва, че състоянието е АКТИВНО .
Нека разгледаме подробностите за сесията от друга сесия, нека я наречем СЕСИЯ 3 заради. Запомнете, СЕСИЯ 1 все още чака.
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>
Така че, за други сесии, СЕСИЯ 2 , т.е. SID 14, еНЕАКТИВНО . СЕСИЯ 1 все още ЧАКВА със събитие enq: TX - row lock contention
.
Нека ангажираме СЕСИЯ 2 -
12:22:18 SQL> commit;
Commit complete.
Elapsed: 00:00:00.01
12:25:43 SQL>
В този момент заключването се освобождава за СЕСИЯ 1 , нека да ангажираме и сесия 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
показва СЕСИЯ 1 чакаше толкова дълго до СЕСИЯ 2 беше извършено.
За да обобщим,ето цялата история на сесия 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>
За да обобщим,ето цялата история на сесия 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>
Сега нека видим коя транзакция всъщност е била отменена и коя е била ангажирана -
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>
Заключение
Според мен най-добрият начин да разберете подробностите за сесията на задънена улица е да регистрирате подробностите възможно най-подробно. В противен случай е кошмар за DBA да разследва, без да е регистрирана подходяща информация. По този въпрос дори разработчикът би сметнал, че е хекулесова задача да коригира и поправи действителния дефект в дизайна, ако подробностите за грешката в застой не се регистрират многословно. И за да завършим с едно изявление, Застой се дължи на недостатък в дизайна, Oracle е само жертвата, а приложението е виновникът. Безизходиците са страшни, но посочват недостатъците в дизайна, които трябва да бъдат отстранени рано или късно.