根据开发反馈,最近每天早上7:30应用会报警,应用的日志显示数据库连接池满了,新的连接被拒绝。
 首先,我做了ASH报告(报告区间:7:25 ~ 7:35),从ASH的等待事件发现enq: TX - row lock contention居然高达76.54%,如下所示:
 
 
Top User Events
 
 
  
   | 
Event | 
   
Event Class | 
   
% Event | 
   
Avg Active Sessions | 
  
   | 
enq: TX - row lock contention | 
   
Application | 
   
76.54 | 
   
0.81 | 
  
   | 
CPU + Wait for CPU | 
   
CPU | 
   
12.76 | 
   
0.14 | 
  
   | 
db file sequential read | 
   
User I/O | 
   
7.40 | 
   
0.08     
 | 
enq: TX - row lock contention等待事件是一种行的等待事件,也就是说同一时刻有多个session请求修改同一行。
 
 下一步就是找这个等待事件主要由哪些SQL引起的:
 
 
Top SQL with Top Events
 
 
  
   | 
SQL ID | 
   
Planhash | 
   
Sampled # of Executions | 
   
% Activity | 
   
Event | 
   
% Event | 
   
Top Row Source | 
   
% RwSrc | 
   
SQL Text | 
  
   | 
    4rm17788qwxuy | 
   
1272661853 | 
   
54 | 
   
69.45 | 
   
enq: TX - row lock contention | 
   
69.45 | 
   
UPDATE | 
   
69.45 | 
   
update shift_case set expertId... | 
  
   | 
    1cqbcdr0ufyk6 | 
   
1272661853 | 
   
10 | 
   
5.20 | 
   
enq: TX - row lock contention | 
   
5.20 | 
   
UPDATE | 
   
5.20 | 
   
update shift_case set daySecti... | 
  
   | 
    1anu5c146v8d7 | 
   
1272661853 | 
   
4 | 
   
1.89 | 
   
enq: TX - row lock contention | 
   
1.89 | 
   
UPDATE | 
   
1.89 | 
   
update shift_case set daySecti... | 
  
   | 
    gbw4zk8jv0n0u | 
   
2588599834 | 
   
10 | 
   
1.57 | 
   
CPU + Wait for CPU | 
   
0.79 | 
   
TABLE ACCESS - BY GLOBAL INDEX ROWID | 
   
0.47 | 
   
select sc.scId, sc.estId, ct.c... | 
  
   | 
    dvmk92c1umc97 | 
   
905317021 | 
   
9 | 
   
1.42 | 
   
CPU + Wait for CPU | 
   
1.42 | 
   
CONNECT BY - NO FILTERING WITH START-WITH | 
   
0.63 | 
   
select h.hospitaluuid id, h.pl...     
 | 
从上表可以得出,SQL_ID=4rm17788qwxuy的SQL语句是罪魁祸首,改SQL语句如下:
 
 
  
   
    | 
4rm17788qwxuy | 
    
update shift_case set expertId = :1 , shiftDate = :2 , daySection = :3 , rcLimit = :4 , orderingCount = :5 , shareRccount = :6 , clinicTypeUuid = :7 , fee = :8 , isTimeDivision = :9 , state = :10 , isopen=:11 , stateTime = :12 , updateTime = sysdate where scId
 =:13 | 
scid是shift_case的主键,也就是说同一时刻有非常多的session在请求更新同一行。
 
好了,既然已经定位到问题就好办了,马上把应用开发人员找来一问,真相大白:原来该应用需要从外部系统获取数据,为了让内部的数据库和外部的尽量保持一致,每次查询外部系统时,会在数据库里执行update语句。
 解决办法也简单:由于每次的Update都会把前一次的update覆盖(等于前面的update做的都是无用功),所以根本没必要每次查询都update,只要最后一次查询做update就可以了。
 
    作者:u010415792 发表于2014-6-4 9:28:56   
原文链接