Enq TX row lock analysis

Resolving Enq: TX – Row Lock Contention with Real-life Scenario Analysis

Whenever Enq: TX - row lock contention wait events occur, most database administrators and consultants typically respond by saying, ‘Oh, that’s an application problem. It’s probably due to a commit or rollback not being executed, and the application design should be revised.‘ I don’t like this answer or that kind of attitude. Additionally, there are dozens of blog posts about the Enq: TX - row lock contention wait event, but they all seem to be just copies of each other.”

I will explain the issue to all DBA kinds using a real-life scenario and equip them with the necessary skills to detect problematic SQL statements. From now on, I hope that anyone facing this wait event will no longer say, ‘Oh, that’s an application problem,’ but instead respond with, ‘The application issued this statement, and it has not been committed or rolled back. During that time, another statement was issued and is now waiting in the queue for the lock to be released.’ With these clear and specific answers, software developers will be able to understand the issue much better.

Short Explanation : This type of contention typically happens in situations where two or more sessions are trying to modify the same row in a table and one session must wait until the lock held by another session is released.

In an Oracle database, whenever a session (Session A) modifies a row (e.g., through an UPDATE, DELETE, or INSERT statement), it acquires a row lock to prevent other sessions from modifying the same row until the transaction is committed or rolled back. Contention occurs when another session (Session B) is blocked because it is trying to access a row that is currently locked by Session A. This results in Session B waiting on the Enq: TX – row lock contention event.

Common Causes:

  • Concurrent Updates: Two or more sessions trying to update the same row simultaneously.
  • Uncommitted Transactions: A session holding a lock due to an uncommitted transaction, causing other sessions to wait.
  • Inadequate Application Design: Situations where multiple sessions frequently access and update the same set of rows, leading to contention.

Resolving Row Lock Contention:

  • Identify Blocking Session: Use Oracle views like V$SESSION, V$LOCK and V$TRANSACTION to identify the session holding the lock and what it is doing.
  • Review Application Logic: Ensure that the application is designed to minimize row lock contention, such as reducing the frequency of updates on the same rows.
  • Commit or Rollback Transactions Promptly: Encourage quick commits or rollbacks to reduce the duration for which locks are held.

As soon as you encounter the Enq: TX - row lock contention wait event, do not immediately kill the session causing the wait. This approach only addresses the immediate issue (saves that moment) but does not solve the root cause.

Step 1: First detect the sql statement in the waiting state (enq: TX – row lock contention) – You may also use Session Browser Menu in TOAD application.

Step 2: We will determine which session this session is waiting for.

SQL> SELECT gvs.inst_id,DECODE (request, 0, 'Holder: ', 'waiter:') || gvl.sid sess,
status,
id1,
id2,
lmode,
request,
gvl.TYPE
FROM gv$lock gvl, gv$session gvs
WHERE (id1, id2, gvl.TYPE) IN (SELECT id1, id2, TYPE
FROM gv$lock
WHERE request > 0)
AND gvl.sid = gvs.sid and gvl.inst_id=gvs.inst_id
ORDER BY id1, request;

Step 3: We have the lock holder session. I have session id and instance number, but I also need session address.

Step 4: We will find out which sql statements executed from this session and not committed or rollbacked. We will basically focus on finding the sql statement (UPDATE,DELETE, MERGE etc.) on DOC_USERS table. It can come from a package / function or executed through a synonym.

Step 5: We will find sql_fulltext.

Step 6: Now We have specific information, we may share with the development team.

The application issued UPDATE DOC_USERS SET DESCRIPTION = :1, ACTIVE = :2, ACTIVE_UNIT = :3, ARCHIVE_ID = :4, BARCODE_TYPE = :5, BARCODE_SIZE = :6, BARCODE_MODEL = :7, BLOCKING_TIME = :8, GENDER = :9, NOT_CHANGABLE = :10, EXT_USER = :11, MENU_NUM = :12, ESIGN_TYPE = :13, THEME_CODE = :14 WHERE ID = :15; on 7/04/2024 23:36:38 and it has not been committed or rolled back. During that time, another statement was issued UPDATE DOC_USERS SET BLOCKING_TIME = :1, LOGIN_FAILURES = :2 WHERE ID = :3 and this one is now waiting in the queue for the lock to be released.

That’s it. Now, it will be easier for them to solve.

For more information, Refer to How to Diagnose Issues Where ‘enq: TX – row lock contention’ Waits are Occurring (Doc ID 1986832.1) , Resolving Issues Where ‘enq: TX – row lock contention’ Waits are Occurring (Doc ID 1476298.1) and WAITEVENT: “enq: TX – row lock contention” Reference Note (Doc ID 1966048.1)

Hope it helps.


Discover More from Osman DİNÇ


Comments

2 responses to “Resolving Enq: TX – Row Lock Contention with Real-life Scenario Analysis”

  1. chagan nath Avatar
    chagan nath

    Hi – nice write up – we observe this time to time on our systems. The wait is caused by select for updates – and sometimes the blocking session has a blank sql id – in this scenario is it ok to kill the blocking sessions which are inactive and have a blank sql id? How does this evolve into a blocking session – perhaps by a previous sql id using the same sid? Also can we kill active holders which are running select for updates and what are the consequences on the app?

    Like

    1. Hi Chagan,
      Since the blocking session is idle, it is normal to see a blank sql_id. You should check v$open_cursor to view all the previous SQL statements executed by this session.
      Most of the time, the SQL statements running in this session should be tuned to execute faster or committed more frequently to shorten the blocking periods for other sessions.
      Killing this inactive session will roll back all the changes made by the killed session. Whether it is safe to do so depends on your application logic.

      Like

Leave your comment