Chapter 07 · DML, Transactions, Read Consistency, Undo, Locks, and Concurrency

Row Locks, Table Locks, ITL, Enqueues, SELECT FOR UPDATE, and Concurrency Semantics

Diagnose Oracle TX/TM locking, SELECT FOR UPDATE behavior, ITL pressure, and blockers with dynamic performance evidence instead of guesswork.

Advanced120–140 minutesTwo-session TX/TM blocking labNOWAIT/WAIT/SKIP LOCKED semanticsFree · optional SELECT_CATALOG_ROLE observerLast reviewed: August 2026

Learning outcomes

Two ServiceHub workers attempt to claim the same work order. One session appears “hung,” another gets an immediate resource-busy error, and an operator sees TX and TM rows in V$LOCK. This lesson connects row locking to Oracle enqueue evidence instead of treating every wait as the same kind of contention.

01

Explain row-level transactional locks and the related TX/TM enqueue evidence.

02

Use SELECT FOR UPDATE with default wait, NOWAIT, WAIT, and SKIP LOCKED semantics appropriately.

03

Diagnose a blocking session with V$SESSION and V$LOCK.

04

Explain Interested Transaction List (ITL) entries and ITL-allocation pressure without cargo-cult tuning.

05

Distinguish transactional enqueues from latch/mutex contention and from deadlocks.

Lab, release, and licensing baseline

Mandatory exercises target the disposable ServiceHub schema in Oracle AI Database Free 26ai. Current documentation was re-checked against RU 23.26.3, SQL Developer 26.2, and SQLcl 26.2. Oracle AI Database Free is limited to 2 foreground CPUs, 2 GB combined SGA/PGA memory, and 12 GB user data and receives no Oracle patches or Support SRs. No paid option, management pack, RAC, Data Guard, Exadata, or cloud service is required. Dynamic performance views shown as observer evidence can require catalog privileges and are clearly separated from application-owner work.

1. Row locks belong to transactions

INSERT, UPDATE, DELETE, MERGE, and SELECT ... FOR UPDATE can acquire row locks. Those locks normally persist until commit or rollback. Oracle also uses table-level DML enqueue structures, commonly observed as TM, while transaction enqueue waits are commonly observed as TX.

The presence of a TM lock does not mean Oracle has escalated thousands of row locks into a SQL Server-style table lock. Oracle does not perform ordinary lock escalation in that sense. Diagnose the requested/held modes and the actual wait event.

2. Two-session blocker: reproduce it safely

sql · one-time setup
DROP TABLE sh07_lock_queue IF EXISTS PURGE;CREATE TABLE sh07_lock_queue (    work_order_id NUMBER PRIMARY KEY,    status_code   VARCHAR2(12) NOT NULL,    claimed_by    VARCHAR2(30));INSERT INTO sh07_lock_queue VALUES (701,'READY',NULL);INSERT INTO sh07_lock_queue VALUES (702,'READY',NULL);COMMIT;
sql · Session A — hold a row lock
UPDATE sh07_lock_queueSET claimed_by = 'worker-A'WHERE work_order_id = 701;-- Do not COMMIT or ROLLBACK yet.
sql · Session B — default behavior waits
UPDATE sh07_lock_queueSET claimed_by = 'worker-B'WHERE work_order_id = 701;-- The prompt waits because Session A holds the conflicting row lock.

This is blocking, not deadlock: Session B waits for A, but A is not waiting for B. End Session B's pending statement if needed, then release A with ROLLBACK before continuing.

3. SELECT FOR UPDATE makes lock intent explicit

Use SELECT FOR UPDATE when the application must read rows and reserve them for a subsequent change in the same transaction. By default Oracle waits for a conflicting lock. NOWAIT fails immediately; WAIT n bounds the wait; SKIP LOCKED deliberately omits locked rows.

sql · Session A locks one row; Session B chooses its policy
-- Session ASELECT work_order_idFROM sh07_lock_queueWHERE work_order_id = 701FOR UPDATE;-- Session B: immediate failure rather than indefinite waitSELECT work_order_idFROM sh07_lock_queueWHERE work_order_id = 701FOR UPDATE NOWAIT;-- Expected: ORA-00054 while A holds the lock.-- Session B: queue-style behavior can deliberately skip locked rowsSELECT work_order_id, status_codeFROM sh07_lock_queueWHERE status_code = 'READY'ORDER BY work_order_idFOR UPDATE SKIP LOCKED;

SKIP LOCKED is useful for competing consumers that may process any available work item. It is inappropriate when the query must return a complete business set, because skipping locked rows is intentionally incomplete.

4. Observe the blocker with V$SESSION and V$LOCK

Use a privileged observer session (for example, a lab DBA account) to inspect dynamic performance views. Do not grant broad catalog access to the application schema merely to make a lab query convenient.

sql · privileged observer evidence
SELECT sid, serial#, username, status,       event, wait_class, blocking_sessionFROM v$sessionWHERE username = 'SERVICEHUB_OWNER'ORDER BY sid;SELECT sid, type, id1, id2, lmode, request, blockFROM v$lockWHERE type IN ('TX','TM')ORDER BY sid, type;

A waiting row-update session commonly reports an event such as enq: TX - row lock contention. LMODE shows the held lock mode and REQUEST the requested mode. These views are evidence of current lock state; they do not tell you the business reason the transaction stayed open.

5. ITL: block-level transaction slots, not another row-lock table

Each data block contains an Interested Transaction List (ITL) that records transactions modifying rows in that block. INITRANS controls initial transaction slots; Oracle can often add slots if block space permits. Under extreme concurrent updates to the same blocks, sessions can wait for an ITL entry, commonly visible as enq: TX - allocate ITL entry.

Do not cargo-cult INITRANS

Do not raise INITRANS globally because you learned the wait-event name. First prove ITL allocation waits on the specific hot object, understand block fullness and concurrent transaction density, then test an object-level change. Higher INITRANS consumes block space.

6. Foreign keys can change locking cost

An unindexed foreign key is legal, but parent-key updates/deletes may require broader child-table work and stronger locking behavior than an indexed child key. In high-concurrency parent maintenance, an index on the foreign-key columns is often important. The decision should follow workload evidence; write-heavy child tables with no parent-key delete/update workload can have different tradeoffs.

7. Blocking is not deadlock, and enqueues are not latches/mutexes

A blocker is a one-way dependency that can resolve when the holder commits or rolls back. A deadlock is a cycle of dependencies; Oracle detects the cycle and raises ORA-00060 to one participant. Latches and mutexes protect internal memory structures and use different wait mechanisms. Treating every “lock” word as the same mechanism leads to incorrect fixes.

sql · release and cleanup
-- End both lab transactions first.ROLLBACK;DROP TABLE sh07_lock_queue PURGE;

8. Production judgment and next step

Keep transactions short, lock rows in a consistent business order, bound user-facing waits, and use SKIP LOCKED only for semantics that permit omission. Diagnose with current waits and blockers before killing sessions. ITL or foreign-key changes should be object/workload-specific. No paid pack is required for V$SESSION/V$LOCK, but viewing all sessions normally requires privileged access.

Lesson 5 creates the cycle that distinguishes a deadlock from ordinary blocking, then connects long snapshots to undo pressure and ORA-01555.

Check your understanding

  1. How is ordinary blocking different from a deadlock?
  2. What does FOR UPDATE NOWAIT change?
  3. When is SKIP LOCKED semantically appropriate?
  4. What does an ITL entry represent?
  5. Does a TM enqueue automatically prove lock escalation?
Review the answers

Blocking can be one-way and resolve when the holder ends its transaction; deadlock is a cyclic wait dependency.

It requests the row lock but returns an error immediately instead of waiting when the resource is busy.

When a worker is allowed to process any currently unlocked item and omission of locked rows is part of the design.

A transaction slot in a data block that helps record transactions modifying rows in that block.

No. TM is table-level DML enqueue evidence; ordinary Oracle row locking does not imply SQL Server-style lock escalation.

Authoritative references

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only Ethereum or ERC-20 compatible assets to this address.