ORA-00054:ресурсът е зает и придобиване с указано NOWAIT е често срещана грешка, наблюдавана в Oracle Database
Справка: Документация на Oracle
Това обикновено се случва, когато се опитате да изпълните DDL върху таблицата, която е заключена от транзакция. Също така се случва, ако операторът select for update се изпълнява с опция NOWAIT
Пример
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
Как да предотвратим грешката ORA-00054
1. Направете DDL в прозореца за поддръжка или извън пиковите часове, когато не се извършва транзакция
2. С 11g имаме DDL_LOCK_TIMEOUT,
Това просто указва колко дълго искате да изчака заключването на DDL
SQL> alter session set ddl_lock_timeout = 600; Session altered. SQL> alter table emp add (middlename varchar2(15)); Table Altered
3. Можем да прекратим транзакцията, която държи ключалките на оракула, и след това да продължим с нея
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' /
След като намерите блокиращата сесия и решите да убиете сесията на oracle, можем да използваме заявката по-долу, за да генерираме sql сесия за убийство
select 'alter system kill session '''||sid||','||serial#||''';' from v$session where sid=&1;
4. Ако получавате ORA-00054:ресурсът е зает и придобийте с указано NOWAIT във формуляра за кандидатстване, след това продължете както следва
Имаме случай, когато срещаме ORA-00054:ресурсът е зает и придобиваме с NOWAIT, посочен във формуляра за кандидатстване. Сега в този случай става много трудно да се намерят ключалките , тъй като приложението не чака заключване. Това обикновено се случва, когато проблемите на приложението избират за актуализиране без опция за изчакване. Можем да намерим ключалки чрез dba_waiters, когато сесията чака заключване. Тъй като се заключва с nowait сесия, не можем просто да я намерим.
Ще трябва да намерим следата на oracle sql за сесията и да възпроизведем проблема. След като следата е налична. Трябва да потърсим err=54 във файла за проследяване
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)'
Редът, който показва грешката, а частта по-горе показва изявлението, което дава грешката
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
Сега, за да намерим блокиращата сесия, трябва да задействаме изявлението в sqlplus с опция 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 ;
Тогава тази сесия ще изчака и лесно можем да намерим блокиращата сесия от dba_waiters и да прекратим блокиращата сесия.
5. С Oracle 11g и Oracle 12c имаме много DDL дейности, които могат да се извършват онлайн без прекъсване на грешката ORA-00054
SQL> create index emp_idx on emp(emp_no) online;
Започвайки от 12c, можете да използвате ONLINE ключова дума с команди DROP INDEX, DROP CONSTRAINT, ALTER INDEX UNUSABLE и SET COLUMN UNUSED
Сродни статии
ORA-00942 таблица или изглед не съществува
ORA-28000 акаунтът е заключен
ORA-28002
ORA-00904:невалиден идентификатор
ORA-01017:невалидно потребителско име/парола; Отказано влизане
променете сесията за унищожаване на системата