sql >> Databáze >  >> RDS >> Oracle

ORA-00054:zdroj je zaneprázdněn a získává se specifikací NOWAIT

ORA-00054:zdroj je zaneprázdněn a získává se specifikací NOWAIT je běžná chyba zaznamenaná v databázi Oracle

Reference: Dokumentace Oracle

K tomu obvykle dochází, když se pokusíte provést DDL na stole, který je uzamčen transakcí. Stává se to také, pokud je příkaz select for update proveden s možností NOWAIT

Příklad

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 předejít chybě ORA-00054

1. Proveďte DDL v okně údržby nebo mimo špičku, když neprobíhá žádná transakce

2.  S 11 g máme DDL_LOCK_TIMEOUT,

Tím jednoduše určíte, jak dlouho chcete, aby čekal na zámek DDL

SQL> alter session set ddl_lock_timeout = 600;
Session altered.

SQL> alter table emp add (middlename varchar2(15));

Table Altered

3.  Můžeme zrušit transakci, která drží věštecké zámky, a poté v ní pokračovat

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'
/

Jakmile najdete blokující relaci a rozhodnete se zabít relaci oracle, můžeme použít níže uvedený dotaz k vygenerování kill session sql

select 'alter system kill session '''||sid||','||serial#||''';' from v$session where sid=&1;

4. Pokud dostáváte ORA-00054:zdroj je zaneprázdněn a získáváte se specifikací NOWAIT ve formuláři žádosti a poté postupujte podle níže

Máme případ, kdy narazíme na ORA-00054:zdroj je zaneprázdněn a získává se s NOWAIT specifikovaným ve formuláři žádosti. Nyní je v tomto případě velmi obtížné najít zámky, protože aplikace na zámek nečeká. K tomu obvykle dochází, když se problémy s aplikací vyberou k aktualizaci bez možnosti čekání. Zámky můžeme najít pomocí dba_waiters, když relace čeká na zámek. Protože se zamyká pomocí nowait session , nemůžeme to jen tak najít.

Budeme muset najít trasování Oracle SQL pro relaci a problém zopakovat. Jakmile bude stopa k dispozici. Musíme hledat err=54 ve trasovacím souboru

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)'

Řádek, který zobrazuje chybu, a část výše ukazuje příkaz, který chybu dává

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

Nyní, abychom našli blokující relaci, musíme spustit příkaz v sqlplus s možností 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 ;

Pak tato relace počká a my můžeme snadno najít blokující relaci z dba_waiters a zastavit blokující relaci.

5. S Oracle 11g a Oracle 12c máme spoustu DDL aktivit, které lze provádět online bez přerušení chyby ORA-00054

SQL> create index  emp_idx on emp(emp_no) online;

Počínaje 12c můžete používat klíčové slovo ONLINE s příkazy DROP INDEX, DROP CONSTRAINT, ALTER INDEX UNUSED a SET COLUMN UNUSED

Související články

Tabulka nebo pohled ORA-00942 neexistuje
ORA-28000 účet je uzamčen
ORA-28002
ORA-00904:neplatný identifikátor
ORA-01017:neplatné uživatelské jméno/heslo; přihlášení odepřeno
změnit relaci zabíjení systému


  1. Získat celkový počet řádků při použití LIMIT?

  2. PostgreSQL převést sloupce na řádky? Přemístit?

  3. Oracle:Co dělá `(+)` v klauzuli WHERE?

  4. Spouštěč MySQL při událostech vložení/aktualizace