ORACLE :11.2.0.3

row cache lock事件
--内存share pool分为library cache,dictionary cache;而row cache lock对象分布在dictionary cache中;
--每次看到类似的告警短信心理都比较发毛;这类属于latch类的资源竞争,相当耗CPU,如果并发量大的话,容易down机
先模拟一个场景:原理,建立一个没有cache的序列,频繁读取nextval,而数据库在读取的同时也要相应的频繁修改这些数据字典中的值
create sequence seq01 start with 1;
开两个会话分别执行:
declare
v_n number;
begin
for i in 1..100000000  loop
select seq04.nextval into v_n from dual;
end loop;
end;
/

首先看下CPU的消耗变化,idle都变为0,后果很严重
[root@11g3 ~]# vmstat 1
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0  75952  14716   7184 735132    0    1    28   249  220  285  6  3 89  2  0
 2  0  75952  14220   7188 735132    0    0     4    28  914 1810  2  0 98  0  0
 0  0  75952  14344   7188 735248    0    0     0   216  990 1869  7  2 89  2  0
 2  1  75952  14096   7188 735240    0    0     0    32  952 1806  3  0 97  0  0
 1  0  75952  14352   7196 735232    0    0     0   160  984 1860  3  2 84 11  0
 0  0  75952  14352   7196 735244    0    0     0    60  973 1817  6  1 93  0  0
 0  0  75952  14352   7196 735244    0    0     0     0  912 1837  0  0 100  0  0
 1  0  75952  14228   7196 735244    0    0     0    28  930 1794  2  1 97  0  0
 1  0  75952  14236   7196 735252    0    0     0    80 1034 1914  6  2 91  1  0
 2  1  75952  14236   7204 735348    0    0   112  6712 3211 6855 30 55 13  2  0
 2  0  75952  14236   7208 735360    0    0    16  7924 3641 7799 37 63  0  0  0
 2  1  75952  13988   7208 735380    0    0    12  8048 3480 7347 37 63  0  0  0
 1  2  75952  13996   7208 735612    0    0   188  7404 3336 6571 44 56  0  0  0
 5  1  75952  12012   7208 736776    0    0   960  6032 3126 4675 56 44  0  0  0
 2  2  75952  12632   7216 736812    0    0    40  5736 2991 4767 60 40  0  0  0
 3  1  75952  12632   7220 736820    0    0    20  6644 3274 5678 54 46  0  0  0
 3  0  75952  12020   7228 736832    0    0    24  6728 3251 5598 55 45  0  0  0
 
两会话的等待事件:
USERNAME                       EVENT
------------------------------ ----------------------------------------------------------------
AIKI                           row cache lock
AIKI                           row cache lock

定位:
SQL> select cache#,cache_name,lock_mode,lock_request,saddr from v$rowcache_parent where lock_mode<>0
  2  /

    CACHE# CACHE_NAME                                                        LOCK_MODE LOCK_REQUEST SADDR
---------- ---------------------------------------------------------------- ---------- ------------ ----------------
        13 dc_sequences                                                              5            0 0000000077DB6F60

SQL> /

    CACHE# CACHE_NAME                                                        LOCK_MODE LOCK_REQUEST SADDR
---------- ---------------------------------------------------------------- ---------- ------------ ----------------
        13 dc_sequences                                                              5            0 0000000077DE0A20

SQL> /

    CACHE# CACHE_NAME                                                        LOCK_MODE LOCK_REQUEST SADDR
---------- ---------------------------------------------------------------- ---------- ------------ ----------------
        13 dc_sequences                                                              5            0 0000000077DB6F60

SQL> /

    CACHE# CACHE_NAME                                                        LOCK_MODE LOCK_REQUEST SADDR
---------- ---------------------------------------------------------------- ---------- ------------ ----------------
        13 dc_sequences                                                              5            0 0000000077DB6F60

SQL> /

    CACHE# CACHE_NAME                                                        LOCK_MODE LOCK_REQUEST SADDR
---------- ---------------------------------------------------------------- ---------- ------------ ----------------
        13 dc_sequences                                                              5            0 0000000077DE0A20
        
--根据saddr在v$session.saddr中去匹配找出会话,可以看两会话间断相互阻塞 (轮流阻塞,不是同时)
select sid,username,status,sql_id,blocking_instance,blocking_session  from v$session where saddr in (
'0000000077DB6F60',
'0000000077DE0A20'
);

  SID	USERNAME	STATUS	SQL_ID	BLOCKING_INSTANCE	BLOCKING_SESSION
1	36	AIKI	ACTIVE	0hhquh91uxqv3	1	50
2	50	AIKI	ACTIVE	0hhquh91uxqv3		
        
 	SID	USERNAME	STATUS	SQL_ID	BLOCKING_INSTANCE	BLOCKING_SESSION        
1	36	AIKI	ACTIVE	0hhquh91uxqv3		                                
2	50	AIKI	ACTIVE	0hhquh91uxqv3	1	36                              

--看下SQL的内容
SQL> select sql_text from v$sqlarea where sql_id='0hhquh91uxqv3';                                                                                                                   
                                                                                                                                                                                    
SQL_TEXT                                                                                                                                                                            
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SELECT SEQ04.NEXTVAL FROM DUAL                                                                                                                                                      

=》果断kill掉会话,先解决;

我们这里实验就不kill,接着验证确认:
SQL> select object_id from dba_objects where object_name='SEQ04' and owner='AIKI';  
                                                                                        
 OBJECT_ID                                                                              
----------                                                                        
     75883                                                                        
                                                                                  
SQL> select to_char(75883,'xxxxxxxxxxxxxx') from dual;                            
                                                                                  
TO_CHAR(75883,'                                                                   
---------------                                                                   
          1286b                                                                   
          

SQL> select  spid from v$process where addr in (select paddr from v$session where sid in (select sid from v$mystat where rownum=1));          
                                                                                                                                    
SPID                                                                                                                                
------------------------                                                                                                            
13364                                                                                                                               
                                                                                                                                    
SQL> alter system set events 'immediate trace name row_cache level 12';         --dump row_cache对象                                                    
                                                                                                                                    
System altered.         

然后在vi oracle11gr3_ora_13364.trc匹配1286b,紧跟着data=后面;可以看到
这序列确实导致了这个问题;

BUCKET 39:                                                                                                                                                                                      
  row cache parent object: address=0x726caf98 cid=13(dc_sequences)                  
  hash=c2e42726 typ=9 transaction=0x761a1018 flags=0000012a                         
  own=0x726cb060[0x715a0018,0x715a0018] wat=0x726cb070[0x78560a38,0x78560a38] mode=X
  status=VALID/UPDATE/-/-/IO/-/-/-/-                                                
  data=                                                                             
=》0001286b 0002000c 000f0002 00050001 000002c1 00000000 00000000 00000000           
  02c10000 00000000 00000000 00000000 00000000 646464ce 64646464 64646464           
  00646464 00800000 00000000 00000000 00000000 00000000 141808c4 00000063           
  00000000 00000000 2d2d0000 2d2d2d2d 2d2d2d2d 2d2d2d2d 2d2d2d2d 2d2d2d2d           
  2d2d2d2d 2d2d2d2d 00002d2d 00000000 00000000 c2e42726 726caf98 00000000           
  717ff0f8 00000000 751377a8 00000000