Row Cache Lock – An interesting case

Suddenly today morning i was reported that an Import is hanging.The dumpfile was of 1Gb  containing few small tables.Immediately, i checked what all are the sessions belonging to impdp and what is session wait for them.Knowing the session wait makes things easier to analyze.

As the import was started by 'SYSTEM'

SELECT NVL(a.username, '(oracle)') AS username,
       a.osuser,
       a.sid,
       a.serial#,
       d.spid AS process_id,
       a.wait_class,
       a.seconds_in_wait,
       a.state,
       a.blocking_session,
       a.blocking_session_status,
       a.module,
       TO_CHAR(a.logon_Time,'DD-MON-YYYY HH24:MI:SS') AS logon_time
FROM   v$session a,
       v$process d
WHERE  a.paddr  = d.addr
AND    a.status = 'ACTIVE'
AND    a.username='SYSTEM'
ORDER BY 1,2;

USERNAME        OSUSER                 SID    SERIAL# PROCESS_ID   WAIT_CLASS                                                   SECONDS_IN_WAIT STATE                BLOCKING_SESSION BLOCKING_SE MODULE          LOGON_TIME
--------------- --------------- ---------- ---------- ------------ ---------------------------------------------------------------- --------------- ------------------- ---------------- ----------- --------------- --------------------
SYSTEM          oracle                1047      16533 32474        Idle                                                     129 WAITING                               UNKNOWN     Data Pump Master 05-MAY-2010 21:28:04

SYSTEM          oracle                1054       1278 32496        Idle                                                     403 WAITING                               UNKNOWN     Data Pump Worker 05-MAY-2010 21:28:07

SYSTEM          oracle                1013       1766 32488        Concurrency                                                     1096 WAITING                               UNKNOWN     Data Pump Worker 05-MAY-2010 21:28:06

I think the best script to find the session wait, which i always use is the one provided by Tanel Poder sw.sql :)

So, lets dig in some more,

SQL> set lines 170
SQL> @sw 1054
old  35:        sid IN (&1)
new  35:        sid IN (1054)

    SID STATE   EVENT                                          SEQ#  WAIT_TIME SEC_IN_WAIT         P1         P2         P3 P1TRANSL
------- ------- ---------------------------------------- ---------- ---------- ----------- ---------- ---------- ---------- ------------------------------------------
   1054 WAITING wait for unread message on broadcast cha        106          0         132 7928361520 8043052960          0

SQL>
SQL> @sw 1013
old  35:        sid IN (&1)
new  35:        sid IN (1013)

    SID STATE   EVENT                                          SEQ#  WAIT_TIME SEC_IN_WAIT         P1         P2         P3 P1TRANSL
------- ------- ---------------------------------------- ---------- ---------- ----------- ---------- ---------- ---------- ------------------------------------------
   1013 WAITING row cache lock                                  286          0        1208          8          0          3

‘row cahe lock’ wait.So what is Row Cache Lock?

In order for DDL to execute, it must acquire a row cache lock to lock the Data Dictionary information. The shared pool contains a cache of rows from the data dictionary that helps reduce physical I/O to the data dictionary tables and allows locking of individual data dictionary rows. The locks on the data dictionary rows are called row cache enqueue locks.

But how and why row lock cache?Digging some more inside

 Lets see what is the enqueue type from v$rowcache

SQL> select p1text,p1,p2text,p2,p3text,p3 from v$session where event='row cache lock';

P1TEXT       P1   P2TEXT   P2 P3TEXT     P3
---------------------------------------------------------------- ----------
cache id       8    mode      0  request        3


SQL> select parameter,count,gets,getmisses,modifications from v$rowcache where cache#=8;

PARAMETER                             COUNT       GETS  GETMISSES MODIFICATIONS
-------------------------------- ---------- ---------- ---------- -------------
dc_objects                              939     537060      25206          3955
dc_object_grants                        180     116117       1784             0

Some of the common Enqueue Types are:-

DC_TABLESPACES
Probably the most likely is allocation of new extents. If extent sizes are set low then the application may constantly be requesting new extents and causing contention. Do you have objects with small extent sizes that are rapidly growing? (You may be able to spot these by looking for objects with large numbers of extents). Check the trace for insert/update activity, check the objects inserted into for number of extents.

DC_SEQUENCES
Check for appropriate caching of sequences for the application requirements.

DC_USERS
Deadlock and resulting “WAITED TOO LONG FOR A ROW CACHE ENQUEUE LOCK!” can occur if a session issues a GRANT to a user, and that user is in the process of logging on to the database.

DC_OBJECTS
Look for any object compilation activity which might require an exclusive lock and thus block online activity.

DC_SEGMENTS
This is likely to be down to segment allocation. Identify what the session holding the enqueue is doing and use errorstacks to diagnose.

In my case enqueue type is “DC_OBJECTS”.Need to check for some object compilation activity.

I had the information that before this import activity some tables were created which used DB-LINK between the target and the source database.

As the tables were created using db-link, i was sure CTAS (create table as select) would have been used.I took a new session and try to create the table using CTAS and db-link and my session was also waiting of row cache lock.Investigation turned over to db-link usage.One of the best way to determine is,who’s using a dblink .It was very helpful to me.

Select /*+ ORDERED */
substr(s.ksusemnm,1,10)||'-'|| substr(s.ksusepid,1,10)      "ORIGIN",
substr(g.K2GTITID_ORA,1,35) "GTXID",
substr(s.indx,1,4)||'.'|| substr(s.ksuseser,1,5) "LSESSION" ,
s2.username,
substr(
   decode(bitand(ksuseidl,11),
      1,'ACTIVE',
      0, decode( bitand(ksuseflg,4096) , 0,'INACTIVE','CACHED'),
      2,'SNIPED',
      3,'SNIPED',
      'KILLED'
   ),1,1
) "S",
substr(w.event,1,10) "WAITING"
from  x$k2gte g, x$ktcxb t, x$ksuse s, v$session_wait w, v$session s2
where  g.K2GTDXCB =t.ktcxbxba
and   g.K2GTDSES=t.ktcxbses
and  s.addr=g.K2GTDSES
and  w.sid=s.indx
and s2.sid = w.sid
/


ORIGIN                GTXID                               LSESSION   USERNAME                       S WAITING
--------------------- ----------------------------------- ---------- ------------------------------ - ----------
gld01-23990        FLXP.9e2e919.112.20.4540          1050.8656  SYS                            A SQL*Net mo

Hmmm…got something…what session is this.What is it doing???Lets check it out

SELECT NVL(s.username, '(oracle)') AS username,
        s.osuser,
        s.sid,
        s.serial#,
        p.spid,
        s.status,
        s.module,
        s.terminal,
        s.machine,
        s.program,
        TO_CHAR(s.logon_Time,'DD-MON-YYYY HH24:MI:SS') AS logon_time
FROM   v$session s,
        v$process p
WHERE  s.paddr  = p.addr
and s.sid=&sid
ORDER BY s.username, s.osuser
/
Enter value for sid: 1050
old  15: and s.sid=&sid
new  15: and s.sid=1050

USERNAME                       OSUSER                                SID    SERIAL# SPID         STATUS   MODULE
------------------------------ ------------------------------ ---------- ---------- ------------ -------- ------------------------------------------------
TERMINAL                       MACHINE                                                          PROGRAM                      LOGON_TIME
------------------------------ ---------------------------------------------------------------- ------------------------------------------------ --------------------
SYS                            oracle                               1050       8656 23991        ACTIVE   sqlplus@gld01 (TNS V1-V3)
                               gld01                                                         sqlplus@gld01 (TNS V1-V3) 05-MAY-2010 11:48:33

The sqlplus session is of ‘SYS’ and is active.The logon time was of a day before.Somebody who tried to create the table did a CTRL+C, but the might be he user’s request didn’t get canceled.Some other reasons might also be possible for this session still to be there.What is this session doing?

SQL>select sql_fulltext from v$sql where (ADDRESS,HASH_VALUE) in (select sql_address,sql_hash_value from v$session where sid= &sid_number); Enter value for sid_number: 1050
old   1: select sql_fulltext from v$sql where (ADDRESS,HASH_VALUE) in (select sql_address,sql_hash_value from v$session where sid= &sid_number)
new   1: select sql_fulltext from v$sql where (ADDRESS,HASH_VALUE) in (select sql_address,sql_hash_value from v$session where sid= 1050)

SQL_FULLTEXT
--------------------------------------------------------------------------------
CREATE TABLE anand.test AS
SELECT b.*, a.creation_date , a.last_modified_date 
  FROM table_name@prd2 a,
          table@prd2 b
 WHERE a.creation_date >= TO_DATE('01-JAN-2010 00:00:00', 'dd-mon-yyyy hh24:mi:s
s')
   AND a.creation_date <= TO_DATE('05-MAY-2010 00:00:00', 'dd-mon-yyyy hh24:mi:s
s')

Ohhhhh….this session is trying to create the table which was in the dumpfile and luckily or unluckily i also tried to create the same table using CTAS with db-link for investigating the row cache lock issue.

Now, the best option was to kill the session and try creating the table using CTAS with db-link and check for the session wait again.

SQL> alter system kill session '1050,8656' immediate;
alter system kill session '1050,8656' immediate
*
ERROR at line 1:
ORA-00031: session marked for kill

SQL>SELECT NVL(s.username, '(oracle)') AS username,
        s.osuser,
        s.sid,
        s.serial#,
        p.spid,
        s.status,
        s.module,
        s.terminal,
        s.machine,
        s.program,
        TO_CHAR(s.logon_Time,'DD-MON-YYYY HH24:MI:SS') AS logon_time
FROM   v$session s,
        v$process p
WHERE  s.paddr  = p.addr
and s.sid=&sid
ORDER BY s.username, s.osuser
/
Enter value for sid: 1050
old  15: and s.sid=&sid
new  15: and s.sid=1050

no rows selected

The session has gone.Lets now try to create the table

SQL>CREATE TABLE anand.test AS SELECT b.*, a.creation_date ,a.last_modified_date  FROM table_name@prd2 a,table@prd2 b
 WHERE a.creation_date >= TO_DATE('01-JAN-2010 00:00:00','dd-mon-yyyy hh24:mi:ss') AND a.creation_date 
/

Table created

After this dropped the test table and tried to import the dumpfile.It got imported successfully.It was a nice learning for me :)

About these ads
  1. Anand,

    Excellent Blog. I am also investigating a performance issue due to “row cache lock” and came across your blog.

    Regards
    Vivek

    • Hi Vivek,

      Thanks a bunch for stopping by here and for the comment :)

      Need to learn alot from you.Hope to meet you in Sangam 10.

      Regards,
      Anand

    • KR
    • August 16th, 2012

    Nice blog. just for future references. I came across ROW CACHE LOCK , when I enabled SQL baseline capture for 11.2.0.2 . it seems to bug in that release.

  1. January 2nd, 2011
  2. January 24th, 2014

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 462 other followers

%d bloggers like this: