sql >> Databasteknik >  >> RDS >> Oracle

ORA-00054:resurs upptagen och förvärv med NOWAIT specificerad

ORA-00054:resurs upptagen och förvärv med NOWAIT specificerad är ett vanligt fel i Oracle Database

Referens: Oracle-dokumentation

Detta händer vanligtvis när du försöker köra en DDL på bordet som är låst av transaktionen. Det händer också om select for update-satsen körs med alternativet NOWAIT

Exempel

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

Hur man förhindrar ORA-00054-felet

1. Gör DDL i underhållsfönstret eller under rusningstid när inga transaktioner pågår

2.  Med 11g har vi DDL_LOCK_TIMEOUT,

Detta anger helt enkelt hur länge du vill att den ska vänta på DDL-låset

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

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

Table Altered

3.  Vi kan döda transaktionen som håller orakellåsen och sedan fortsätta med den

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

När du har hittat blockeringssessionen och bestämt dig för att döda oracle-sessionen kan vi använda nedanstående fråga för att generera kill-sessionen sql

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

4.Om du får ORA-00054:resurs upptagen och förvärv med NOWAIT specificerad i ansökningsformuläret, fortsätt sedan enligt nedan

Vi har fall där vi stöter på ORA-00054:resurs upptagen och förvärva med NOWAIT som anges i ansökningsformuläret. Nu i det här fallet blir det väldigt svårt att hitta låsen eftersom applikationen inte väntar på låset. Detta händer vanligtvis när applikationsproblem väljer för uppdatering utan väntealternativ. Vi kan hitta lås genom dba_waiters när sessionen väntar på låset. Eftersom den låser med nowait session kan vi inte bara hitta den.

Vi måste hitta oracle sql-spårningen för sessionen och återskapa problemet. När spåret är tillgängligt. Vi måste leta efter err=54 i spårningsfilen

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

Raden som visar felet och delen ovan visar satsen som ger felet

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

Nu för att hitta blockeringssessionen måste vi avfyra uttalandet i sqlplus med alternativet 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 ;

Sedan väntar den här sessionen och vi kan enkelt hitta blockeringssessionen från dba_waiters och döda blockeringssessionen.

5.Med Oracle 11g och Oracle 12c har vi många DDL-aktiviteter som kan göras online utan avbrott av felet ORA-00054

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

Från och med 12c kan du använda ONLINE nyckelord med kommandona DROP INDEX, DROP CONSTRAINT, ALTER INDEX UNUSBLE och SET COLUMN UNUSED

Relaterade artiklar

ORA-00942 tabell eller vy finns inte
ORA-28000 kontot är låst
ORA-28002
ORA-00904:ogiltig identifierare
ORA-01017:ogiltigt användarnamn/lösenord; inloggning nekad
ändra systemavlivningssession


  1. Den flerdelade identifieraren kunde inte bindas

  2. Välj slumpmässig rad för varje grupp

  3. Oracle-uppdateringen hänger sig

  4. Hur testar man om en MySQL-fråga lyckades ändra databastabelldata?