ORA-00054: recurso ocupado y adquirir con NOWAIT especificado o tiempo de espera caducado

¿Por qué recibo este error de base de datos cuando actualizo una tabla?

ERROR en la línea 1: ORA-00054: recurso ocupado y adquirir con NOWAIT especificado o tiempo de espera caducado

Su tabla ya está bloqueada por alguna consulta. Al igual que ha ejecutado “seleccionar para la actualización” y aún no ha confirmado / revertido y nuevamente ha disparado la consulta de selección. Haga un commit / rollback antes de ejecutar su consulta.

de aquí ORA-00054: recurso ocupado y adquirir con NOWAIT especificado

También puede buscar el SQL, el nombre de usuario, la máquina, la información del puerto y llegar al proceso real que contiene la conexión

SELECT O.OBJECT_NAME, S.SID, S.SERIAL#, P.SPID, S.PROGRAM,S.USERNAME, S.MACHINE,S.PORT , S.LOGON_TIME,SQ.SQL_FULLTEXT FROM V$LOCKED_OBJECT L, DBA_OBJECTS O, V$SESSION S, V$PROCESS P, V$SQL SQ WHERE L.OBJECT_ID = O.OBJECT_ID AND L.SESSION_ID = S.SID AND S.PADDR = P.ADDR AND S.SQL_ADDRESS = SQ.ADDRESS; 

Por favor maten la sesión de Oracle

Use la consulta a continuación para verificar la información de la sesión activa

 SELECT O.OBJECT_NAME, S.SID, S.SERIAL#, P.SPID, S.PROGRAM, SQ.SQL_FULLTEXT, S.LOGON_TIME FROM V$LOCKED_OBJECT L, DBA_OBJECTS O, V$SESSION S, V$PROCESS P, V$SQL SQ WHERE L.OBJECT_ID = O.OBJECT_ID AND L.SESSION_ID = S.SID AND S.PADDR = P.ADDR AND S.SQL_ADDRESS = SQ.ADDRESS; 

matar como

 alter system kill session 'SID,SERIAL#'; 

(Por ejemplo, alter system kill session '13,36543' 😉

Referencia http://abeytom.blogspot.com/2012/08/finding-and-fixing-ora-00054-resource.html

Hay un trabajo muy fácil para este problema.

Si ejecuta un rastreo 10046 en su sesión (google esto … demasiado para explicar). Verá que antes de cualquier operación DDL, Oracle hace lo siguiente:

LOCK TABLE ‘TABLE_NAME’ NO ESPERE

Entonces, si otra sesión tiene una transacción abierta, se obtiene un error. Entonces la solución es … Redoble de batería por favor. Emita su propio candado antes del DDL y omita el mensaje ‘NO ESPERE’.

Nota especial:

si está dividiendo / soltando particiones, oracle simplemente bloquea la partición. – entonces puedes bloquear la partición de partición.

Entonces … Los siguientes pasos arreglan el problema.

  1. LOCK TABLE ‘TABLE NAME’; – ‘esperará’ (los desarrolladores llaman a esto colgado). hasta la sesión con la transacción abierta, commits. Esta es una cola. entonces puede haber varias sesiones por delante. pero NO saldrás del error.
  2. Ejecute DDL. Su DDL ejecutará un locking con NO WAIT. Sin embargo, su sesión ha adquirido el locking. Entonces eres bueno.
  3. DDL se confirma automáticamente. Esto libera los lockings.

Las sentencias DML ‘esperarán’ o, como los desarrolladores lo llaman ‘colgar’ mientras la tabla está bloqueada.

Utilizo esto en el código que se ejecuta desde un trabajo para soltar particiones. Funciona bien. Está en una base de datos que se inserta constantemente a una velocidad de varios cientos de inserts / second. Sin errores.

si te estás preguntando Haciendo esto en 11g. He hecho esto en 10g antes también en el pasado.

Este error ocurre cuando el recurso está ocupado. Compruebe si tiene restricciones referenciales en la consulta. O incluso las tablas que ha mencionado en la consulta pueden estar ocupadas. Es posible que se dediquen a algún otro trabajo que se enumerará definitivamente en los siguientes resultados de la consulta:

 SELECT * FROM V$SESSION WHERE STATUS = 'ACTIVE' 

Encuentra el SID,

 SELECT * FROM V$OPEN_CURSOR WHERE SID = --the id 

Esto sucede cuando una sesión distinta a la utilizada para modificar una tabla tiene un locking probablemente debido a un DML (actualizar / eliminar / insertar). Si está desarrollando un nuevo sistema, es probable que usted o alguien de su equipo emita la statement de actualización y que pueda matar la sesión sin demasiadas consecuencias. O puede comprometerse con esa sesión una vez que sepa quién tiene la sesión abierta.

Si tiene acceso a un sistema de administración de SQL, úselo para encontrar la sesión ofensiva. Y tal vez matarlo.

Puede usar v $ session y v $ lock y otros, pero le sugiero que busque en google cómo encontrar esa sesión y luego cómo matarla.

En un sistema de producción, realmente depende. Para oracle de 10g en adelante, podrías ejecutar

 LOCK TABLE mytable in exclusive mode; alter table mytable modify mycolumn varchar2(5); 

En una sesión separada, pero tenga listo lo siguiente en caso de que tarde demasiado.

 alter system kill session '.... 

Depende de qué sistema tenga, es más probable que los sistemas antiguos no se comprometan cada vez. Ese es un problema ya que puede haber lockings de larga duración. Por lo tanto, su locking evitaría cualquier locking nuevo y esperaría un locking que quién sabe cuándo se lanzará. Es por eso que tienes lista la otra statement. O podría buscar scripts PLSQL que hagan cosas similares automáticamente.

En la versión 11g hay una nueva variable de entorno que establece un tiempo de espera. Creo que probablemente haga algo similar a lo que describí. Tenga en cuenta que los problemas de locking no desaparecen.

 ALTER SYSTEM SET ddl_lock_timeout=20; alter table mytable modify mycolumn varchar2(5); 

Finalmente, puede ser mejor esperar hasta que haya pocos usuarios en el sistema para realizar este tipo de mantenimiento.

Su problema parece que está mezclando operaciones DML y DDL. Vea esta URL que explica este problema:

http://www.orafaq.com/forum/t/54714/2/

Simplemente verifica el proceso que contiene la sesión y Mátalo. Está de vuelta a la normalidad.

Debajo de SQL encontrará su proceso

 SELECT s.inst_id, s.sid, s.serial#, p.spid, s.username, s.program FROM gv$session s JOIN gv$process p ON p.addr = s.paddr AND p.inst_id = s.inst_id; 

Entonces mátalo

 ALTER SYSTEM KILL SESSION 'sid,serial#' 

O

algún ejemplo que encontré en línea parece necesitar la identificación de la instancia y alterar la sesión de matanza del sistema ‘130,620, @ 1’;

En mi caso, estaba bastante seguro de que era una de mis propias sesiones que estaba bloqueando. Por lo tanto, era seguro hacer lo siguiente:

  • Encontré la sesión ofensiva con:

    SELECT * FROM V$SESSION WHERE OSUSER='my_local_username';

    La sesión estaba inactiva , pero aún mantenía el locking de alguna manera. Tenga en cuenta que es posible que necesite usar alguna otra condición WHERE en su caso (por ejemplo, pruebe los campos USERNAME o MACHINE ).

  • Eliminó la sesión utilizando la ID y el SERIAL# adquiridos anteriormente:

    alter system kill session ', ';

Me las arreglé para golpear este error al crear una tabla! Obviamente, no había ningún problema de contención en una mesa que aún no existía. La CREATE TABLE contiene una CONSTRAINT fk_name FOREIGN KEY que hace referencia a una tabla bien poblada. Tuve que:

  • Elimine la cláusula FOREIGN KEY de la instrucción CREATE TABLE
  • Crear un ÍNDICE en la columna FK
  • Crea el FK

Tuve este error cuando tenía 2 scripts que estaba ejecutando. Tuve:

  • Una sesión SQL * Plus conectada directamente utilizando una cuenta de usuario de esquema (cuenta n.º 1)
  • Otra sesión de SQL * Plus conectada utilizando una cuenta de usuario de esquema diferente (cuenta n.º 2), pero conectándose a través de un enlace de base de datos como la primera cuenta

Ejecuté una tabla desplegable, luego la creación de tabla como cuenta n. ° 1. Ejecuté una actualización de la tabla en la sesión de la cuenta # 2. No cometió cambios. Vuelva a ejecutar el guión de caída / creación de tabla como cuenta n.º 1. Obtuve un error en el comando drop table x .

Lo resolví ejecutando COMMIT; en la sesión de cuenta SQL * Plus # 2.

También me enfrento al problema similar. Nada de progtwigdor tiene que hacer para resolver este error. Informé a mi equipo de DBA de Oracle. Matan la sesión y funcionan como un encanto.

La solución dada por el enlace de Shashi es la mejor … no hay necesidad de contactar a dba u otra persona

hacer una copia de seguridad

 create table xxxx_backup as select * from xxxx; 

eliminar todas las filas

 delete from xxxx; commit; 

inserta tu copia de seguridad

 insert into xxxx (select * from xxxx_backup); commit;