Professional Documents
Culture Documents
What is a TX lock?
A TX lock is acquired when a transaction initiates its first change and is held until the transaction does a
COMMIT or ROLLBACK. It is used mainly as a queuing mechanism so that other sessions can wait for the
transaction to complete.
The TX lock is interesting as it can occur not only in Mode 6 but Mode 4 as well – see example further
down.
TX lock in mode 6 is an application coding and design problem and can only be alleviated by changing
application code, most likely with more frequent and explicit COMMIT statements and other minor code
changes. The only way to assist is to help identify the objects and queries causing these waits.
Mode 4 – row share lock usually due to Unique Index, Foreign Key or Bitmap Index
Mode 6 – row exclusive lock which a transaction holds until commit or rollback is issued.
Knowing just which lock mode is requested is vital, as the troubleshooting for TX Mode 4 locks will be
different from what is used to troubleshoot Mode 6.
When a TX lock contention occurs, Enq: TX <> wait events are encountered.
A typical AWR report when the database encounters Enq: TX Row Lock contention displays a profile as
below:
This query identifies the Session ID and SQL (could be more than one) of the sessions holding the locks
while the waits are taking place:
select sid, sql_text
from v$session s, v$sql q
where sid in
(select sid from v$session
where state in ('WAITING')
and wait_class != 'Idle'
and event='enq: TX - row lock contention'
and (q.sql_id = s.sql_id or q.sql_id = s.prev_sql_id)
);
The following query provides more details e.g. object causing the locking, sql_id etc
e.g.
SID TY ID1 ID2 LMODE REQUEST
----- ---- ---------- ---------- ---------- ----------
588 TX 524299 936708 0 6
587 TX 524299 936708 6 0
Here SID 587 is holding an exclusive row lock (mode 6) and SID 588 is requesting an exclusive row lock,
which results in enq: TX - row lock contention wait.
select sid,event FROM v$session_wait WHERE wait_time= 0 AND event like 'enq%';
SID EVENT
---------- ----------------------------------------------------------------
588 enq: TX - row lock contention
The following query gives information on the segment/s involved – the information in this view is stored
until a database restart so it may also include past history.
Lock mode 4
There may be cases where primary key constraints, a unique constraint or a unique index can cause
contention. In mode 4, a TX wait can occur if there is a potential duplicate in a unique index. When two
sessions try to insert the same key value the second session must wait to see if an ORA-001 should be
raised. This can cause the "enq: TX - row lock contention" wait event.
2 sessions attempt an insert with the same primary key – first session not yet committed. These are the
observations:
SID EVENT
---------- ----------------------------------------------------------------
588 enq: TX - row lock contention
SID 588 is waiting for a TX lock by SID 587 in share mode (4) – SID 588 has a TX lock on its own
transaction (mode 6). X`
A similar situation can occur with bitmap indexes.
For past issues i.e. once data has been flushed from gv$active_session_history,
dba_hist_active_sess_history can be used to drill down on the event to get further details on sessions
waiting by sampling between 2 time windows e.g.,
To find out more about the blocking and blocked sessions, this script can be used find out the sql_id’s of
the blocking session and the blocked session (this can be tweaked to get sql_text but would become
unworkable with large SQL queries).
select
s.username username,
s.sid,
e.event event,
e.p1text,
e.p1,
e.state
from v$session s, v$session_wait e
where s.username is not null
and s.sid = e.sid
and e.event like '%enq:%'
order by s.username, upper(e.event);
The P1 value of this type of lock is always the same – 1415053318. For mode 4 locks, this value is
1415053316.
The following query when the row locks are in progress will also show the lock mode
Lock Mode
-------- ---------
TX 6
SELECT sid, blocking_session, event FROM v$session LEFT OUTER JOIN v$sqlarea USING (sql_id) WHERE
nvl(blocking_session,sid) IN (SELECT holding_session FROM dba_blockers);
SELECT name
FROM v$archived_log
WHERE 12205614783505 BETWEEN first_change# AND next_change# - 1;
NAME
------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------
/u02/data2/fra/EM12/archivelog/1_30089_900792223.dbf
Start Logminer
EXECUTE
dbms_logmnr.add_logfile(logfilename=>'/u02/data2/fra/EM12/archivelog/1_30089_900792223.dbf');
EXECUTE dbms_logmnr.start_logmnr(options=>dbms_logmnr.dict_from_online_catalog);
SELECT sql_redo
FROM v$logmnr_contents
WHERE xidusn = 2
AND xidslt = 9
AND xidsqn = 881866;
SQL_REDO
------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------
set transaction read write;
select * from "SYSTEM"."ANIL" where ROWID = 'AATUKqAABAAAn2ZAAA' for update;
select * from "SYSTEM"."ANIL" where ROWID = 'AATUKqAABAAAn2ZAAB' for update;
select * from "SYSTEM"."ANIL" where ROWID = 'AATUKqAABAAAn2ZAAE' for update;
End logminer
EXECUTE dbms_logmnr.end_logmnr;