Ошибка ora 00054

Why am I getting this database error when I update a table?

ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired

Josep's user avatar

Josep

4952 gold badges6 silver badges16 bronze badges

asked Jan 30, 2011 at 11:59

sun's user avatar

1

Your table is already locked by some query. For example, you may have executed «select for update» and have not yet committed/rollbacked and fired another select query. Do a commit/rollback before executing your query.

Paweł Obrok's user avatar

Paweł Obrok

22.5k8 gold badges74 silver badges70 bronze badges

answered Jan 30, 2011 at 12:02

user258367's user avatar

user258367user258367

3,2372 gold badges18 silver badges17 bronze badges

4

from here ORA-00054: resource busy and acquire with NOWAIT specified

You can also look up the sql,username,machine,port information and get to the actual process which holds the connection

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;

Community's user avatar

answered Aug 10, 2012 at 3:29

Abey Tom's user avatar

Abey TomAbey Tom

1,4261 gold badge12 silver badges7 bronze badges

5

Please Kill Oracle Session

Use below query to check active session info

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;

kill like

alter system kill session 'SID,SERIAL#';

(For example, alter system kill session '13,36543' ;)

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

user5670895's user avatar

answered Feb 10, 2014 at 11:01

Chan Myae Thu's user avatar

Chan Myae ThuChan Myae Thu

1,0541 gold badge9 silver badges9 bronze badges

4

There is a very easy work around for this problem.

If you run a 10046 trace on your session (google this… too much to explain). You will see that before any DDL operation Oracle does the following:

LOCK TABLE ‘TABLE_NAME’ NO WAIT

So if another session has an open transaction you get an error. So the fix is… drum roll please. Issue your own lock before the DDL and leave out the ‘NO WAIT’.

Special Note:

if you are doing splitting/dropping partitions oracle just locks the partition.
— so yo can just lock the partition subpartition.

So…
The following steps fix the problem.

  1. LOCK TABLE ‘TABLE NAME’; — you will ‘wait’ (developers call this hanging). until the session with the open transaction, commits. This is a queue. so there may be several sessions ahead of you. but you will NOT error out.
  2. Execute DDL. Your DDL will then run a lock with the NO WAIT. However, your session has aquired the lock. So you are good.
  3. DDL auto-commits. This frees the locks.

DML statements will ‘wait’ or as developers call it ‘hang’ while the table is locked.

I use this in code that runs from a job to drop partitions. It works fine. It is in a database that is constantly inserting at a rate of several hundred inserts/second. No errors.

if you are wondering. Doing this in 11g. I have done this in 10g before as well in the past.

answered Apr 29, 2013 at 21:15

Bob's user avatar

BobBob

2,4964 gold badges21 silver badges18 bronze badges

8

This error happens when the resource is busy. Check if you have any referential constraints in the query. Or even the tables that you have mentioned in the query may be busy. They might be engaged with some other job which will be definitely listed in the following query results:

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

Find the SID,

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

answered Jul 15, 2013 at 8:28

Arunchunaivendan's user avatar

3

In my case, I was quite sure it was one of my own sessions which was blocking. Therefore, it was safe to do the following:

  • I found the offending session with:

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

    The session was inactive, but it still held the lock somehow. Note, that you may need to use some other WHERE condition in your case (e.g. try USERNAME or MACHINE fields).

  • Killed the session using the ID and SERIAL# acquired above:

    alter system kill session '<id>, <serial#>';

Edited by @thermz: If none of the previous open-session queries work try this one. This query can help you to avoid syntax errors while killing sessions:

  • SELECT 'ALTER SYSTEM KILL SESSION '''||SID||','||SERIAL#||''' immediate;' FROM V$SESSION WHERE OSUSER='my_local_username_on_OS'

answered Sep 3, 2013 at 10:27

wrygiel's user avatar

wrygielwrygiel

5,0703 gold badges24 silver badges29 bronze badges

1

This happens when a session other than the one used to alter a table is holding a lock likely because of a DML (update/delete/insert). If you are developing a new system, it is likely that you or someone in your team issues the update statement and you could kill the session without much consequence. Or you could commit from that session once you know who has the session open.

If you have access to a SQL admin system use it to find the offending session. And perhaps kill it.

You could use v$session and v$lock and others but I suggest you google how to find that session and then how to kill it.

In a production system, it really depends. For oracle 10g and older, you could execute

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

In a separate session but have the following ready in case it takes too long.

alter system kill session '....

It depends on what system do you have, older systems are more likely to not commit every single time. That is a problem since there may be long standing locks. So your lock would prevent any new locks and wait for a lock that who knows when will be released. That is why you have the other statement ready. Or you could look for PLSQL scripts out there that do similar things automatically.

In version 11g there is a new environment variable that sets a wait time. I think it likely does something similar to what I described. Mind you that locking issues don’t go away.

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

Finally it may be best to wait until there are few users in the system to do this kind of maintenance.

answered Jul 15, 2013 at 19:49

Arturo Hernandez's user avatar

Arturo HernandezArturo Hernandez

2,7293 gold badges28 silver badges35 bronze badges

2

select
   c.owner,
   c.object_name,
   c.object_type,
   b.sid,
   b.serial#,
   b.status,
   b.osuser,
   b.machine
from
   v$locked_object a,
   v$session b,
   dba_objects c
where
   b.sid = a.session_id
and
   a.object_id = c.object_id;
   
   ALTER SYSTEM KILL SESSION 'sid,serial#';

answered Sep 26, 2019 at 17:52

harun ugur's user avatar

harun ugurharun ugur

1,68818 silver badges17 bronze badges

As mentioned in other answers, this error is caused by concurrent DML operations running in other sessions. This causes Oracle to fail to lock the table for DDL with the default NOWAIT option.

For those without admin permissions in the database or who cannot kill/interrupt the other sessions, you can also precede your DDL operation with:

alter session set DDL_LOCK_TIMEOUT = 30;
--Run your DDL command, e.g.: alter table, etc.

I was receiving this error repeatedly in a database with background jobs doing large insert/update operations, and altering this parameter in the session allowed the DDL to continue after a few seconds of waiting for the lock.

For further information, see the comment from rshdev on this answer, this entry on oracle-base or the official docs on DDL_LOCK_TIMEOUT.

answered Aug 27, 2021 at 18:40

divieira's user avatar

divieiradivieira

8859 silver badges17 bronze badges

1

Just check for process holding the session and Kill it. Its back to normal.

Below SQL will find your process

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;

Then kill it

ALTER SYSTEM KILL SESSION 'sid,serial#'

OR

some example I found online seems to need the instance id as well
alter system kill session ‘130,620,@1’;

answered Nov 27, 2014 at 3:30

Mathavan John's user avatar

I had this error happen when I had 2 scripts I was running. I had:

  • A SQL*Plus session connected directly using a schema user account (account #1)
  • Another SQL*Plus session connected using a different schema user account (account #2), but connecting across a database link as the first account

I ran a table drop, then table creation as account #1.
I ran a table update on account #2’s session. Did not commit changes.
Re-ran table drop/creation script as account #1. Got error on the drop table x command.

I solved it by running COMMIT; in the SQL*Plus session of account #2.

answered May 23, 2017 at 19:46

vapcguy's user avatar

vapcguyvapcguy

7,0321 gold badge55 silver badges51 bronze badges

2

I managed to hit this error when simply creating a table! There was obviously no contention problem on a table that didn’t yet exist. The CREATE TABLE statement contained a CONSTRAINT fk_name FOREIGN KEY clause referencing a well-populated table. I had to:

  • Remove the FOREIGN KEY clause from the CREATE TABLE statement
  • Create an INDEX on the FK column
  • Create the FK

answered Nov 19, 2015 at 15:05

bwperrin's user avatar

bwperrinbwperrin

6605 silver badges12 bronze badges

2

I solved this problem by closing one of my IDE tabs.

PL/SQL Developer
Version 10.0.5.1710

answered Sep 1, 2022 at 14:26

Alexander Martins's user avatar

I also face the similar Issue. Nothing programmer has to do to resolve this error. I informed to my oracle DBA team. They kill the session and worked like a charm.

answered Jan 17, 2017 at 20:50

Shakeer Hussain's user avatar

Shakeer HussainShakeer Hussain

2,1727 gold badges27 silver badges52 bronze badges

3

Solution given by Shashi’s link is the best… no needs to contact dba or someone else

make a backup

create table xxxx_backup as select * from xxxx;

delete all rows

delete from xxxx;
commit;

insert your backup.

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

answered Mar 27, 2013 at 9:23

tafibo's user avatar

2

ORA-00054 error message:

ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired

Causes

ORA-00054 error is a commonly seen error by Oracle users and occurs when a user tries to execute a LOCK TABLE or SELECT FOR UPDATE command with the NOWAIT keyword when the resource is unavailable. DDL or DML operations are being run concurrently without proper commits. In most cases, Error ORA-00054? occurs from a session. Any session that has referenced the table and any structural change attempt, such as adding a column, requires an “exclusive” lock.

Solutions

This happens when a session other than the one used to alter a table is holding a lock likely because of a DML (update/delete/insert). If you are developing a new system, it is likely that you or someone in your team issues the update statement and you could kill the session without much consequence. Or you could commit from that session once you know who has the session open.

If you have access to a SQL admin system use it to find the offending session. And perhaps kill it. You could use v$session and v$lock and others but I suggest you google how to find that session and then how to kill it.

Actions

You have choices for avoiding the ORA-00054 error:

  • Re-run the change late at night when the database is idle.
  • Do all DDL during a maintenance window with all end-users locked-out.
  • Kill the sessions that are preventing the exclusive lock. 

From above three options the easiest and the quickest method is the kill the blocking session. Use below query to check active session info. There are some other sessions which are blocking this sessions.

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;
alter system kill session 'SID,SERIAL#';

Screenshots

ORA-00054 error when executing DML.

ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired

Find blocking session

Find blocking database session
Find blocking database session

Kill the blocking session

Kill and Alter DB session
Kill the blocking session

After session kill, type the SQL again it will be execute successfully.

Fixing ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
Fixing ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired

Oh, that’s a way of the How to solve | ORA-00054: ‘resource busy and acquire with NOWAIT specified or timeout expired’ on my website at this time. If you have any suggestions for additional issues just leave a comment below, and I’ll see what I can do. You can find more Oracle related articles from here.

Please feel free to share this post with anyone who might be interested..

About Author

Charaka Hettiarachchi

Charaka is a personal tech blogger who writes about important tech trends on web development, wordpress, day today technical issues. I work as a system support engineer and has over 6 years of industry experience.

Thanks for the info user ‘user712934’

You can also look up the sql,username,machine,port information and get to the actual process which holds the connection

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;

ORA-00054

ORA-00054: ресурс занят и при обращении с NOWAIT указателем

Причина:

Команды LOCK TABLE или SELECT FOR UPDATE используются на ресурсе который не доступен. Так как вы указали NOWAIT, вы снова вернетесь к командной подсказке.

Действие:

Попробуйте повторить операцию снова несколько минут, или если вы хотите дождаться таблицы, удалите ключевое слово NOWAIT.

ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired error occurs when you try to lock a resource that is already locked and busy with execution. If two Oracle connections attempt to lock a resource such as a table, view, or other resource, the first connection will lock the resource, and the second resource will be unable to obtain the lock for the resource. The error will be thrown immediately if the NOWAIT option is used to obtain the lock. If the WAIT option is used to obtain the lock, the lock command will wait until the timeout expires and then throw an error ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired

The error will be displayed to Oracle users who attempt to execute a LOCK TABLE or SELECT FOR UPDATE command with the NOWAIT keyword.
If the user waits a few minutes before attempting to run the query again, the active session will have completed and the error message will not reappear. Another option is to find the active session and terminate it in order to free up the table and rerun the query. Reduce the likelihood of this error occurring in the future. Make the table read-only if it will not be used for inserting, updating, or deleting data.

The Problem

If two Oracle database sessions attempt to obtain a lock on a resource, one will obtain the lock for updating, while the other will throw this error. Two Oracle database connections must be created to reproduce this error. Execute the lock command for a table in the first session. With a write operation, the table will be locked. When you attempt to obtain a lock from the second session, the lock will throw this error.

Session 1

lock table employee in exclusive mode NOWAIT;

Session 1 output

Lock succeeded.

Session 2

lock table employee in exclusive mode NOWAIT;

Session 2 output

lock table employee in exclusive mode NOWAIT
Error report -
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
00054. 00000 -  "resource busy and acquire with NOWAIT specified or timeout expired"
*Cause:    Interested resource is busy.
*Action:   Retry if necessary or increase timeout.

Solution 1

When you run an Oracle query from the application, the lock is created before the query is executed. When the query execution is finished, it will either be committed or rolled back. The second thread will attempt to lock the same resource as the first thread during concurrent access from the application. This will result in the error. If this error occurs, modify your code to retry after a certain amount of time. This will fix the problem. In this case, the first lock will be completed after the query is executed.

Solution 2

If the error occurs from your application and the error is consistently reproducible, then the commit or rollback is not happening. Verify in your code make sure commit is done after successful execution. In case of failure, the roll back should be called explicitly. The commit or roll back will unlock the table for another oracle user to use.

Session 1

lock table employee in exclusive mode NOWAIT;

Session 1 output

Lock succeeded.

Session 2

lock table employee in exclusive mode NOWAIT;

Session 2 output

lock table employee in exclusive mode NOWAIT
Error report -
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
00054. 00000 -  "resource busy and acquire with NOWAIT specified or timeout expired"
*Cause:    Interested resource is busy.
*Action:   Retry if necessary or increase timeout.

Session 1

rollback;

Session 1 output

Rollback complete.

Session 2

lock table employee in exclusive mode NOWAIT;

Session 2 output

Lock succeeded.

Solution 3

The table is not required to lock if it is locked to execute a select statement for reading purposes. The table can be defined as read-only. Reduce the likelihood of this errors happening again in the future. If the table will not be used for inserting, updating, or deleting data, make it read-only.

alter table employee read only;

Execute the following command to restore the read-only table.

alter table employee read write;

Solution 4

If you are receiving the error from the second session of the application and are unable to obtain control of the first, you will be unable to execute commit or roll back to release the lock. The first session should be ended in this case by terminating the session. There are two ways to end a session: POST TRANSACTION and IMMEDIATE. After completing the current transaction, the POST TRANSACTION will terminate the session. The IMMEDIATE transaction will end the current session immediately without waiting for the current transaction to finish. The transactions will be rolled back in this case.

To identify the session that needs to be terminated, run the below command. the query will return the Sid and serial number.

select a.sid, a.serial# from v$session a, v$locked_object b, dba_objects c
where b.object_id = c.object_id and a.sid = b.session_id and OBJECT_NAME='EMPLOYEE';

Output

sid.    serial#
----------------
25      64920

The following command will terminate the session and the lock will be released.

alter system kill session '<Sid>, <serial>' POST_TRANSACTION | IMMEDIATE ;
alter system kill session '25, 64920' IMMEDIATE ;

or

alter system kill session '25, 64920' POST_TRANSACTION ;

Solution 5

If the first session query takes longer to complete and the second session executes before the first session is finished, the first session cannot be terminated. The first session is valid, and the second session should be postponed until the first session is finished. The second session should be set to wait until the first session is finished. For the lock timeout expiry, the timeout configuration should be increased. The following command will set the lock’s timeout. The lock command should not use the NOWAIT option in this case.

alter session set ddl_lock_timeout = 600;

Session 1

lock table employee in exclusive mode;

Session 1 output

Lock succeeded.

Session 2

lock table employee in exclusive mode;

Session 2 output

-- wait for a long period till the first session to complete

Session 1

rollback;

Session 1 output

Rollback complete.

Session 2

-- wait for a long period till the first session to complete

Session 2 output

Lock succeeded.

.

Понравилась статья? Поделить с друзьями:
  • Ошибка ora 00020
  • Ошибка ora 00001 unique constraint violated
  • Ошибка ora 12547
  • Ошибка or pmia 14 что это
  • Ошибка ora 12541 tns no listener