ORA-00054:zasoby zajęte i pozyskiwanie z określonym NOWAIT jest częstym błędem występującym w Oracle Database
Odniesienie: dokumentacja Oracle
Zwykle dzieje się tak, gdy próbujesz wykonać DDL na tabeli, która jest zablokowana przez transakcję. Dzieje się tak również, jeśli instrukcja select for update jest wykonywana z opcją NOWAIT
Przykład
SQL> alter table emp add (middlename varchar2(15)); * ERROR at line 1: ORA-00054: resource busy and acquire with NOWAIT specified SQL> create index emp_idx on emp(emp_no); * ERROR at line 1: ORA-00054: resource busy and acquire with NOWAIT specified SQL> Select * from emp for update NOWAIT; * ERROR at line 1: ORA-00054: resource busy and acquire with NOWAIT specified
Jak zapobiec błędowi ORA-00054
1. Wykonaj DDL w oknie konserwacji lub poza godzinami szczytu, gdy nie odbywa się żadna transakcja
2. Przy 11g mamy DDL_LOCK_TIMEOUT,
To po prostu określ, jak długo chcesz czekać na blokadę DDL
SQL> alter session set ddl_lock_timeout = 600; Session altered. SQL> alter table emp add (middlename varchar2(15)); Table Altered
3. Możemy zabić transakcję, która blokuje blokady Oracle, a następnie kontynuować
column sid_ser format a12 heading 'session,|serial#'; column username format a12 heading 'os user/|db user'; column process format a9 heading 'os|process'; column spid format a7 heading 'trace|number'; column owner_object format a35 heading 'owner.object'; column locked_mode format a13 heading 'locked|mode'; column status format a8 heading 'status'; select substr(to_char(l.session_id)||','||to_char(s.serial#),1,12) sid_ser, substr(l.os_user_name||'/'||l.oracle_username,1,12) username, l.process, p.spid, substr(o.owner||'.'||o.object_name,1,35) owner_object, decode(l.locked_mode, 1,'No Lock', 2,'Row Share', 3,'Row Exclusive', 4,'Share', 5,'Share Row Excl', 6,'Exclusive',null) locked_mode, substr(s.status,1,8) status from v$locked_object l, all_objects o, v$session s, v$process p where l.object_id = o.object_id and l.session_id = s.sid and s.paddr = p.addr and s.status != 'KILLED' /
Po znalezieniu sesji blokującej i podjęciu decyzji o zabiciu sesji oracle, możemy użyć poniższego zapytania, aby wygenerować sesję zabijania sql
select 'alter system kill session '''||sid||','||serial#||''';' from v$session where sid=&1;
4. Jeśli otrzymujesz ORA-00054:zajęty zasób i kup z określonym NOWAIT w formularzu zgłoszeniowym, a następnie postępuj jak poniżej
Mamy przypadek, w którym napotykamy ORA-00054:zasób zajęty i pozyskiwanie z NOWAIT określonym w formularzu wniosku. Teraz w tym przypadku znalezienie blokad staje się bardzo trudne, ponieważ aplikacja nie czeka na blokadę. Zwykle dzieje się tak, gdy problemy z aplikacją wybierają aktualizację bez opcji oczekiwania.Możemy znaleźć blokady za pośrednictwem dba_waiters, gdy sesja czeka na blokadę.Ponieważ blokowanie odbywa się za pomocą sesji nowait , nie możemy jej po prostu znaleźć.
Musimy znaleźć ślad Oracle SQL dla sesji i odtworzyć problem. Gdy ślad będzie dostępny. Musimy poszukać err=54 w pliku śledzenia
PARSING IN CURSOR #18446744071497070208 len=167 dep=1 uid=173 oct=3 lid=173 tim=3315832569154 hv=817497356 ad='31afc8bcd0' sqlid='6gvfwr8sbn18c' SELECT GROUP_MARK_ID FROM MTL_INV_SERIAL_NUMBERS WHERE CURRENT_ORGANIZATION_ID = :B3 AND INVENTORY_ITEM_ID = :B2 AND SERIAL_NUMBER = :B1 FOR UPDATE OF GROUP_MARK_ID NOWAIT END OF STMT PARSE #18446744071497070208:c=53,e=52,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=1,plh=1906360410,tim=3315832569152 BINDS #18446744071497070208: Bind#0 oacdty=02 mxl=22(21) mxlc=00 mal=00 scl=00 pre=00 oacflg=03 fl2=1206001 frm=00 csi=00 siz=80 off=0 kxsbbbfp=ffffffff7c203028 bln=22 avl=03 flg=05 value=23 Bind#1 oacdty=02 mxl=22(21) mxlc=00 mal=00 scl=00 pre=00 oacflg=03 fl2=1206001 frm=00 csi=00 siz=0 off=24 xsbbbfp=ffffffff7c203040 bln=22 avl=05 flg=01 value=11111 Bind#2 oacdty=01 mxl=32(30) mxlc=00 mal=00 scl=00 pre=00 oacflg=03 fl2=1206001 frm=01 csi=871 siz=0 off=48 kxsbbbfp=ffffffff7c203058 bln=32 avl=08 flg=01 value="1222333" EXEC #18446744071497070208:c=1167,e=1167,p=0,cr=9,cu=1,mis=0,r=0,dep=1,og=1,plh=1906360410,tim=3315832570599 ERROR #18446744071497070208:err=54 tim=3315832570735 STAT #18446744071497070208 id=1 cnt=0 pid=0 pos=1 obj=0 op='FOR UPDATE (cr=0 pr=0 pw=0 time=0 us)'
Wiersz, który pokazuje błąd i część powyżej, pokazuje stwierdzenie, które powoduje błąd
SELECT GROUP_MARK_ID FROM MTL_INV_SERIAL_NUMBERS WHERE CURRENT_ORGANIZATION_ID = :B3 AND INVENTORY_ITEM_ID = :B2 AND SERIAL_NUMBER = :B1 FOR UPDATE OF GROUP_MARK_ID NOWAIT
Teraz, aby znaleźć sesję blokującą, musimy uruchomić instrukcję w sqlplus z opcją NOWAIT
SELECT GROUP_MARK_ID FROM MTL_INV_SERIAL_NUMBERS WHERE CURRENT_ORGANIZATION_ID = :B3 AND INVENTORY_ITEM_ID = :B2 AND SERIAL_NUMBER = :B1 FOR UPDATE OF GROUP_MARK_ID ;
Wtedy ta sesja będzie czekać i możemy łatwo znaleźć sesję blokującą od dba_waiters i zabić sesję blokującą.
5. Z Oracle 11g i Oracle 12c mamy wiele czynności DDL, które można wykonać online bez przerywania błędu ORA-00054
SQL> create index emp_idx on emp(emp_no) online;
Począwszy od 12c, możesz używać słowa kluczowego ONLINE z poleceniami DROP INDEX, DROP CONSTRAINT, ALTER INDEX UNUSABLE i SET COLUMN UNUSED
Powiązane artykuły
Tabela lub widok ORA-00942 nie istnieje
ORA-28000 konto jest zablokowane
ORA-28002
ORA-00904:nieprawidłowy identyfikator
ORA-01017:nieprawidłowa nazwa użytkownika/hasło; Odmowa logowania
zmień sesję zabijania systemu