Practice 18 - Handling Enqueue Waits
Practice 18 - Handling Enqueue Waits
Practice 18 - Handling Enqueue Waits
Practice 18
Practice Target
In this practice, you will simulate an enqueue wait event and use multiple tools to diagnose it.
2. Start Putty, login to srv1 as oracle. Invoke SQL*Plus and login to ORADB as sysdba. In the rest
of this practice, this window is referred to as the admin window.
sqlplus / as sysdba
3. Start another two Putty sessions. In each of them login to srv1 as oracle, invoke SQL*Plus and
login to ORADB as soe. In the rest of this practice, these windows are referred to as the client
windows.
sqlplus soe/soe
4. In one of the client windows, obtain the current time then issue the update statement that
follows. Take a note of the retrieved output time.
SELECT TO_CHAR(SYSDATE, 'MM/DD/YY HH24:MI:SS') ctime FROM DUAL;
In the following steps, you will diagnose the enqueue wait events that are currently held in the
system. At this stage, the user is currently blocked.
6. In the admin window, issue the following query to detect the sessions involved in the locking
issue.
The query returns the SID of the blocking session and the waiting session.
col SESSIONS format A20
SELECT DECODE(REQUEST,0,'Holder SID: ','Waiter SID: ') ||
SID SESSIONS, ID1, ID2, LMODE, REQUEST, TYPE
FROM V$LOCK
WHERE (ID1, ID2, TYPE) IN (SELECT ID1, ID2, TYPE FROM V$LOCK WHERE REQUEST > 0)
ORDER BY ID1, REQUEST;
7. Run the following query to display more information about the waiting session.
set pagesize 20
col INFO for a200
SELECT
'SID: '|| S.SID || CHR(10) ||
'USERNAME: '|| S.USERNAME || CHR(10) ||
'EVENT: ' || S.EVENT || CHR(10) ||
'DESCRIPTION: ' || T.DESCRIPTION || CHR(10) ||
'CURRENT STATEMENT: ' || Q.SQL_TEXT || CHR(10) ||
'WAITING TIME (s): ' || S.SECONDS_IN_WAIT || CHR(10) ||
'P1TEXT: ' || S.P1TEXT || CHR(10) ||
'P1: ' || S.P1 || CHR(10) ||
'P2TEXT: ' || S.P2TEXT || CHR(10) ||
'P2: ' || S.P2 || CHR(10) ||
'P3TEXT: ' || S.P3TEXT || CHR(10) ||
'P3: ' || S.P3
AS INFO
FROM V$SESSION S, V$LOCK L, V$LOCK_TYPE T, V$SQL Q
WHERE S.SID = L.SID AND T.TYPE=L.TYPE AND S.SQL_ID = Q.SQL_ID
AND L.REQUEST>0;
8. Run the following query to construct a query that retrieves the row affected by the locked row.
Obtain the SID of waiting session from the output of the preceding step.
SELECT 'SELECT * FROM "' || O.OWNER || '"."' || O.OBJECT_NAME || '"
WHERE ROWID = DBMS_ROWID.ROWID_CREATE(1, ' || S.ROW_WAIT_OBJ# || ', ' ||
S.ROW_WAIT_FILE# || ', ' || ROW_WAIT_BLOCK# || ', ' ||
ROW_WAIT_ROW# || ');'
FROM DBA_OBJECTS O, V$SESSION S
WHERE S.ROW_WAIT_OBJ# = O.OBJECT_ID AND S.SID = &V_WSID;
In the preceding steps, you diagnosed the wait events of currently locked sessions. In the following
steps, you will diagnose the issue after the lock is released but the lock information is still in the
memory (information about them can be obtained from the V$ views).
As the enqueue wait events have been recently released, we can obtain information about them from
ASH and from the V$ views.
10. In the blocking session window, release the lock (by issuing a rollback or commit statement).
ROLLBACK;
In the preceding steps, we dealt with an issue that has been reported to us.
But sometimes, enqueue wait events happen in brief periods. Sometimes the users do not report
about the delay cause by them because they believe the system is just like that.
Part of the DBA proactive monitoring routine should be to monitor the 'enq: TX - row lock contention'.
If they frequently take place in the system, we need to perform an investigation.
14. Run the following query to retrieve the enqueue wait events ever recorded in the database since
the last time the instance was started.
col EVENT format a40
col WAIT_CLASS format a11
SELECT EVENT, AVERAGE_WAIT,
TO_CHAR(ROUND(TIME_WAITED/100),'999,999,999') TIME_SECONDS, WAIT_CLASS
FROM V$SYSTEM_EVENT
WHERE EVENT LIKE 'enq%'
ORDER BY TIME_WAITED;
15. Run the following query to return the objects that were waited for their locks to be released.
The query returns the number of waits, not the wait time.
col OBJECT_NAME for a10
col stats for a20
SELECT OBJECT_NAME, SUBSTR(STATISTIC_NAME, 1, 30) STATS, VALUE
FROM V$SEGMENT_STATISTICS
WHERE ( STATISTIC_NAME IN( 'ITL waits' , 'row lock waits' ))
AND VALUE>0 AND OBJECT_NAME NOT LIKE 'BIN$%'
ORDER BY VALUE DESC;
16. Retrieve the SQL statements that waited the most for wait events of type "Application".
In many cases, this corresponds to the TX enqueue waits.
col SQL_TEXT for a30
SELECT ROUND(APPLICATION_WAIT_TIME / 1000000) WAIT_TIME_S,
SQL_ID, SUBSTR(SQL_TEXT,1,30) SQL_TEXT
FROM V$SQLSTATS
WHERE APPLICATION_WAIT_TIME >0
ORDER BY APPLICATION_WAIT_TIME DESC FETCH FIRST 10 ROW ONLY;
In the following steps, you will diagnose the enqueue wait events that happened in the past
(information about them is not available in the V$ views anymore).
As the enqueue wait events happened in the past, we only can obtain information about it from AWR
or ASH history. If the issue is older than the AWR retention period, we cannot obtain information
about it.
18. Produce an AWR report with HTML format using the most recent snapshots that cover the
incident time. Give the produced report the name awr_enq_tx.html
@ ?/rdbms/admin/awrrpt.sql
Summary
• Enqueue wait events are events that should not frequently occur in healthy systems. They can
be diagnosed using various performance tools.