- Error code
- ORA-00054
- Product
- Oracle Database
- Versions
- Oracle Database 19c, 21c, 23ai and 26ai (wording differs: see below)
- Category
- Locking, Transactions & Sessions
- Last reviewed
- 24 October 2026
On this page
What it means
ORA-00054 means your statement needed a lock that another session holds and was not allowed to wait for it (NOWAIT, or a lock timeout that ran out), so Oracle returned at once instead of queueing.
Most Oracle statements simply wait when another session holds a lock they need. ORA-00054 appears when waiting is not allowed or the allowed wait has run out: LOCK TABLE ... NOWAIT, SELECT ... FOR UPDATE NOWAIT, and DDL such as ALTER TABLE, DROP TABLE or TRUNCATE on a table with uncommitted changes. For DDL the wait is set by the DDL_LOCK_TIMEOUT parameter, whose default of 0 means NOWAIT.
Current releases rewrite the message to describe the lock: its type and name (TM is the DML lock on a table), and two identifiers. In Oracle's own example the first identifier, described as "Table", is the object number of the locked table. Oracle's reference gives a query on GV$SESSION and GV$LOCK that uses these values to find the session holding the lock and how many seconds it has held it. Oracle Database 19c and 21c print only "resource busy and acquire with NOWAIT specified or timeout expired".
The holder is usually a session with an uncommitted transaction on the table: a developer's SQL tool with an unfinished UPDATE, a batch job, or an application connection that never committed. Once it commits or rolls back, the lock is released and your statement will succeed.
Common causes
- DDL (ALTER TABLE, DROP TABLE, TRUNCATE, CREATE INDEX without ONLINE) on a table another session has changed but not committed, with DDL_LOCK_TIMEOUT at its default of 0.
- SELECT ... FOR UPDATE NOWAIT on rows that another transaction has locked.
- LOCK TABLE ... NOWAIT on a table that another session holds a conflicting lock on.
- A SQL tool session (SQL Developer, SQL*Plus) left with uncommitted changes, holding locks for a long time.
- A deployment script that runs DDL while the application is still writing to the table.
Diagnose it
Read-only These queries only read the data dictionary (USER_, ALL_ and DBA_ views) and dynamic performance views (V$). They do not change data, privileges or settings, so they are safe to run first. DBA_ and V$ views need the matching privileges.
Which object is locked? (current message format)
For a TM lock, look up the first identifier from the message in DBA_OBJECTS (or ALL_OBJECTS for objects you can see).
SELECT owner, object_name, object_type
FROM dba_objects
WHERE object_id = 74855; -- the first identifier from the message The table that is locked. With the 19c message you already know the table from your own statement.
Which sessions hold locks on the table?
V$LOCKED_OBJECT lists the sessions holding DML locks on each object. Needs SELECT access to the V$ views and DBA_OBJECTS, normally a DBA. Oracle's ORA-00054 page gives an equivalent query on GV$SESSION and GV$LOCK that filters on the lock type and the two identifiers from the message, and works across RAC instances.
SELECT s.sid, s.serial#, s.username, s.status, s.osuser, s.machine,
s.module, s.program, s.logon_time, lo.locked_mode
FROM v$locked_object lo
JOIN dba_objects o ON o.object_id = lo.object_id
JOIN v$session s ON s.sid = lo.session_id
WHERE o.owner = 'SHOP'
AND o.object_name = 'ORDERS'; The session (SID and SERIAL#), the user, the machine and the program holding the lock. A STATUS of INACTIVE with an old LOGON_TIME usually means an idle session with an open transaction.
Is anything already queued behind the holder?
SELECT sid, username, blocking_session, event, seconds_in_wait
FROM v$session
WHERE blocking_session IS NOT NULL; Sessions that are waiting, and the SID blocking each one. If many sessions wait on the same SID, ending that transaction is urgent.
How to fix it
Each fix is labelled with what it changes. Try read-only checks and the least invasive fix first, and test changes outside production.
Let the holding session commit or roll back
Changes dataOracle's Action is to retry, and if the lock is still held, identify the session and end its transaction. Contact the owner of the session found above and ask them to finish: in their session, not yours.
-- run in the session that holds the lock
COMMIT; -- or ROLLBACK, if the changes are not wanted
Let DDL wait for the lock instead of failing at once
Changes configurationDDL_LOCK_TIMEOUT sets how many seconds DDL waits in the DML lock queue; 0 (the default) means NOWAIT. Setting it for your session makes a deployment wait for short transactions to finish instead of failing. If the lock is still held when the time runs out, you get the error again.
ALTER SESSION SET ddl_lock_timeout = 60;
ALTER TABLE shop.orders ADD (notes VARCHAR2(400));
Wait a bounded time for row locks
Changes dataWhere code uses NOWAIT, consider WAIT n, which (per the SELECT reference) waits up to n seconds for the rows to become available and then returns control to you; handle the error raised when they are still locked. Keep NOWAIT where an immediate answer is the point, for example to skip a job that is already being processed, and handle the error there.
SELECT id, status
FROM shop.orders
WHERE id = :order_id
FOR UPDATE WAIT 5;
Last resort: end the holding session
Changes database stateOracle's reference lists disconnecting or terminating the session as an option. Do this only when the owner cannot be reached and the work cannot wait. Use the SID and SERIAL# from the diagnostic query.
Caution: Needs the ALTER SYSTEM privilege. All uncommitted work in that session is rolled back, which for a large transaction can take a long time, and the user or job loses its connection. Check SID and SERIAL# twice: they identify one specific session.
ALTER SYSTEM KILL SESSION '147,41814';
Examples
Altering a table while another session has an uncommitted change
Not reproduced here: no Oracle Database is installed for this site. The result shows the current message format from Oracle's error reference, whose own example is a DROP TABLE blocked by a TM lock; the object number 74855 is illustrative and differs on every database. Oracle Database 19c prints "resource busy and acquire with NOWAIT specified or timeout expired".
-- session 1 (not committed)
UPDATE orders SET status = 'SHIPPED' WHERE id = 42;
-- session 2
ALTER TABLE orders ADD (notes VARCHAR2(400));
ORA-00054: Failed to acquire a lock (Type: "TM", Name: "DML", Description: "Synchronizes accesses to an object") because it is currently held by another session. The resource being locked can be identified by 74855 ("Table") and 0 ("operation")
SELECT FOR UPDATE NOWAIT on a row another transaction holds
Not reproduced here: no Oracle Database is installed for this site. The result shows the 19c wording from Oracle's error reference. Current releases print the longer "Failed to acquire a lock" form, describing the lock type and its identifiers; that exact text for a row lock is not shown in Oracle's reference, so it is not reproduced here.
-- session 1 (not committed)
UPDATE orders SET status = 'PICKING' WHERE id = 42;
-- session 2
SELECT id, status
FROM orders
WHERE id = 42
FOR UPDATE NOWAIT;
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired
How to prevent it
Run DDL in a maintenance window or with a session DDL_LOCK_TIMEOUT, and check V$LOCKED_OBJECT for open transactions on the table before you start. Commit or roll back in SQL tools as soon as you finish a change, rather than leaving an open transaction in a window you are no longer using.
In application code, use NOWAIT or WAIT n only where you handle ORA-00054 deliberately, for example by skipping a row another worker has already claimed, and keep transactions short so locks are released quickly.
Common questions
How do I find which session is locking my table?
Query V$LOCKED_OBJECT joined to DBA_OBJECTS and V$SESSION for the table, or use Oracle's GV$SESSION and GV$LOCK query with the lock type and identifiers from the current message. You get the SID, SERIAL#, user, machine and program of the holder.
Why does ALTER TABLE fail instantly instead of waiting?
DDL waits only as long as DDL_LOCK_TIMEOUT allows, and its default of 0 means NOWAIT. Set ddl_lock_timeout for your session to let the DDL wait for short transactions.
Should I kill the blocking session?
Only as a last resort. Ending it rolls back all its uncommitted work and disconnects the user or job. First ask the owner to commit or roll back, or wait and retry.
Learn more on CodeWithSQL
Official documentation
- ORA-00054 (Oracle Database Error Messages)
- DDL_LOCK_TIMEOUT (Oracle Database Reference 19c)
- V$LOCKED_OBJECT (Oracle Database Reference 19c)
- LOCK TABLE (Oracle SQL Language Reference 19c)
Last technically reviewed 24 October 2026; examples and diagnostics run on Oracle Database Error Messages reference (26ai, 21c and 19c); not run locally. Messages and explanations follow Oracle's Database Error Messages reference; no Oracle Database was available, so the examples were not run locally.