sql >> Base de Datos >  >> RDS >> Oracle

ORA-00054:recurso ocupado y adquisición con NOWAIT especificado

ORA-00054:recurso ocupado y adquisición con NOWAIT especificado es un error común visto en Oracle Database

Referencia: documentación de Oracle

Esto generalmente sucede cuando intenta ejecutar un DDL en la tabla que está bloqueada por transacción. También sucede si se ejecuta la instrucción select for update con la opción NOWAIT

Ejemplo

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

Cómo prevenir el error ORA-00054

1. Realice el DDL en la ventana de mantenimiento o fuera de las horas pico cuando no se esté realizando ninguna transacción

2.  Con 11g, tenemos DDL_LOCK_TIMEOUT,

Esto simplemente especifica cuánto tiempo te gustaría que esperara el bloqueo DDL

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

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

Table Altered

3.  Podemos eliminar la transacción que contiene los bloqueos de Oracle y luego proceder con ella

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

Una vez que haya encontrado la sesión de bloqueo y haya decidido eliminar la sesión de Oracle, podemos usar la siguiente consulta para generar el sql de la sesión de eliminación

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

4. Si obtiene ORA-00054:recurso ocupado y adquisición con NOWAIT especificado en el formulario de solicitud, luego proceda como se indica a continuación

Tenemos un caso en el que encontramos ORA-00054:recurso ocupado y adquisición con NOWAIT especificado en el formulario de solicitud. Ahora, en este caso, se vuelve muy difícil encontrar los bloqueos, ya que la aplicación no espera el bloqueo. Esto generalmente sucede cuando los problemas de la aplicación seleccionan la actualización sin opción de espera. Podemos encontrar bloqueos a través de dba_waiters cuando la sesión espera el bloqueo. Como se está bloqueando con la sesión sin espera, no podemos simplemente encontrarlo.

Tendremos que encontrar el seguimiento de SQL de Oracle para la sesión y reproducir el problema. Una vez que el rastro está disponible. Necesitamos buscar err=54 en el archivo de rastreo

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

La línea que muestra el error y la parte anterior muestra la instrucción que genera el error

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

Ahora, para encontrar la sesión de bloqueo, debemos activar la declaración en sqlplus con la opción 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 ;

Entonces esta sesión esperará y podemos encontrar fácilmente la sesión de bloqueo de dba_waiters y eliminar la sesión de bloqueo.

5.Con Oracle 11g y Oracle 12c, tenemos muchas actividades DDL que se pueden realizar en línea sin interrupción del error ORA-00054

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

A partir de 12c, puede usar la palabra clave ONLINE con los comandos DROP INDEX, DROP CONSTRAINT, ALTER INDEX UNUSABLE y SET COLUMN UNUSED

Artículos relacionados

ORA-00942 la tabla o vista no existe
ORA-28000 la cuenta está bloqueada
ORA-28002
ORA-00904:identificador no válido
ORA-01017:nombre de usuario/contraseña no válidos; inicio de sesión denegado
alterar la sesión de eliminación del sistema