Oracle
 sql >> Base de données >  >> RDS >> Oracle

ORA-00054 :ressource occupée et acquisition avec NOWAIT spécifié

ORA-00054 :ressource occupée et acquisition avec NOWAIT spécifié est une erreur courante rencontrée dans Oracle Database

Référence : Documentation Oracle

Cela se produit généralement lorsque vous essayez d'exécuter un DDL sur la table qui est verrouillée par une transaction. Cela se produit également si l'instruction select for update est exécutée avec l'option NOWAIT

Exemple

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

Comment éviter l'erreur ORA-00054

1.Faites le DDL dans la fenêtre de maintenance ou les heures creuses lorsqu'aucune transaction n'est en cours

2. Avec 11g, nous avons DDL_LOCK_TIMEOUT,

Ceci indique simplement combien de temps vous souhaitez qu'il attende le verrou DDL

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

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

Table Altered

3. Nous pouvons tuer la transaction qui contient les verrous Oracle, puis continuer

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

Une fois que vous avez trouvé la session de blocage et décidé de tuer la session oracle, nous pouvons utiliser la requête ci-dessous pour générer la session kill sql

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

4.Si vous obtenez ORA-00054 :ressource occupée et acquisition avec NOWAIT spécifié dans le formulaire de demande, puis procédez comme ci-dessous

Nous avons un cas où nous rencontrons ORA-00054 :ressource occupée et acquise avec NOWAIT spécifié dans le formulaire de demande. Dans ce cas, il devient très difficile de trouver les verrous car l'application n'attend pas le verrou. Cela se produit généralement lorsque des problèmes d'application sélectionnent une mise à jour sans option d'attente. Nous pouvons trouver des verrous via dba_waiters lorsque la session attend le verrou. Comme il se verrouille avec nowait session , nous ne pouvons pas simplement le trouver.

Nous devrons trouver la trace Oracle SQL pour la session et reproduire le problème. Une fois la trace disponible. Nous devons rechercher err=54 dans le fichier de trace

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 ligne qui montre l'erreur et la partie ci-dessus montre la déclaration qui donne l'erreur

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

Maintenant, pour trouver la session de blocage, nous devons déclencher l'instruction dans sqlplus avec l'option 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 ;

Ensuite, cette session attendra et nous pourrons facilement trouver la session de blocage à partir de dba_waiters et tuer la session de blocage.

5.Avec Oracle 11g et Oracle 12c, nous avons beaucoup d'activités DDL qui peuvent être effectuées en ligne sans interruption de l'erreur ORA-00054

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

À partir de 12c, vous pouvez utiliser le mot-clé ONLINE avec les commandes DROP INDEX, DROP CONSTRAINT, ALTER INDEX UNUSABLE et SET COLUMN UNUSED

Articles connexes

ORA-00942 la table ou la vue n'existe pas
ORA-28000 le compte est verrouillé
ORA-28002
ORA-00904 :identifiant invalide
ORA-01017 :nom d'utilisateur/mot de passe invalide ; connexion refusée
alter system kill session