sábado, 27 de julho de 2013

DBA - Resolvendo ORA-00054 - resource busy and acquire with NOWAIT specified

Olá meus amigos,

Ao tentar truncar um tabela no banco de dados, me deparei com o erro ORA-00054.
Este erro significa que você está tentando manipular algum objeto (digo objeto e não arquivo, pois pode tratar-se de um índice) que já está sendo utilizado por outro recurso. Gerando lock no objeto. Neste caso, era realmente um índice que estava com o status UNUSABLE, impedindo o funcionamento do comando TRUNCATE na tabela específica.

Vamos ver uma maneira de resolver tal problema.



1) Tentativa de realizar o truncate na tabela FIN_OUT do owner PROD

SQL> TRUNCATE TABLE PROD.FIN_OUT
  2  /
TRUNCATE TABLE PROD.FIN_OUT
                        *
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified

2) Verificando os status dos índices

SQL> select distinct status from dba_indexes;

STATUS
--------
UNUSABLE
N/A
VALID


SQL> select owner, index_name from dba_indexes where status = 'UNUSABLE';

OWNER                                INDEX_NAME
------------------------------ ------------------------------
PROD                                    IDX_FIN



VALID: índice válido
N/A: Índice para partition table
UNUSABLE: índice inutilizável (causando nosso problema)

3) Verificando se o objeto está lockado por outra sessão através da view v$locked_object

SQL> select substr(o.object_name,1,25)  objeto,
       l.session_id                     session_id,
       l.oracle_username                ora_user,
       l.os_user_name                   os_user
from   dba_objects o, v$locked_object l
where  l.object_id = o.object_id
order by 1,3,4;

OBJETO                    SESSION_ID ORA_USER                       OS_USER
------------------------- ---------- ------------------------------ ---------------------------
FIN_OUT                        5244                      PROD                  root


Perceba que a sessão 5244 está lockando o objeto.

4) Com um SELECT simples na v$session, descobrimos que a sessão está inativa

SQL> select sid, SERIAL#, USERNAME, status  from v$session where sid  = 5244;

       SID    SERIAL# USERNAME                       STATUS
---------- ---------- ------------------------------ --------
      5244      49767    PROD                       INACTIVE


5) Realizei o kill nesta sessão, eliminando-a do banco de dados.

SQL> alter system kill session '5244, 49767' immediate;

System altered.

6) Apliquei o rebuild online no índice que estava inutilizável.

SQL> alter index BR_PROD.IDX_FIN rebuild online;

Index altered.

SQL> select distinct status from dba_indexes;

STATUS
--------
N/A
VALID

Após atuação, consegui truncar minha tabela sem nenhum problema
SQL> TRUNCATE TABLE PROD.FIN_OUT;

Table truncated.


Por hoje é só, até o próximo artigo.