暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

诊断案例二:临时表引发的竞争

原创 Eygle 2019-07-24
581

这是帮助一个网友解决的一个问题,通过MSN交流,以下是问题的解决过程及思路,供大家参考。

问:如果一个DB里面的几个存储过程总是跑不完,同样的存储过程在其他的6个省都很正常,数据库里没有锁,数据库和Server上面的空间足够。正常的情况几分钟就能运行完,现在都n多小时了还没有运行完,会是什么原因呢?

答:检查v$session_wait,看系统在等什么?

提示:如果你的系统慢,通常是存在等待,v$session_wait是你应该优先检查的视图。

下面是这位网友发过来的查询结果,这里截取了主要的部分:

SID SEQ#  EVENT   P1TEXT  P1  P1RAW  P2TEXT  P2  
13 7210  library cache pin handle address 3172526924 BD18EB4C pin address 3205742908
33 16179 library cache pin handle address 3172526924 BD18EB4C pin address 3206485860
32 14721 library cache pin handle address 3172526924 BD18EB4C pin address 3206555324
27 54913 library cache pin handle address 3172526924 BD18EB4C pin address 3205741540
30 16169 library cache lock handle address 3174604528 BD389EF0 lock address3206478252

通过以上信息注意到,数据库目前正在经历Library Cache Pin和Library Cache Lock的等待和竞争。我要求她执行本章上文中讲到过的SQL,并提供结果:

SQL> select ADDR,KGLHDADR,KGLHDPAR,KGLNAOWN,KGLNAOBJ,KGLNAHSH,KGLHDOBJ
  2  from X$KGLOB
  3  where KGLHDADR ='BD18EB4C'; 
ADDR     KGLHDADR KGLHDPAR  KGLNAOWN  KGLNAOBJ  KGLNAHSH KGLHDOBJ
---------- ------------------ -------------------------- -------------------------- ------
01920880   BD18EB4C  BD18EB4C          truncate table iptt_pm_all   653109544 BD18E8D4
SQL> SELECT a.SID, a.username, a.program, b.addr, b.kglpnadr, b.kglpnuse,
  2         b.kglpnses, b.kglpnhdl, b.kglpnlck, b.kglpnmod, b.kglpnreq
  3 FROM v$session a, x$kglpn b WHERE a.saddr = b.kglpnuse AND b.kglpnmod <> 0
  4 AND b.kglpnhdl IN (SELECT p1raw FROM v$session_wait WHERE event LIKE 'library%') ;
SID USERNAME PROGRAM       ADDR     KGLPNADR KGLPNUSE KGLPNSES KGLPNHDL KGLPNLCK KGLPNMOD
--- -------- ------------- -------- -------- -------- -------- -------- -------- --------
 30 IPNMS  sqlplus@gs-db 0191BEC0 BF2024C4 BE0AE940 BE0AE940 BD18EB4C BF1FA208   3
 54 IPNMS   sqlplus@gs-db 0191BEC0 BF13814C BE0BB360 BE0BB360 BD389EF0 00          3
SQL> SELECT sql_text FROM v$sqlarea
  3 WHERE (v$sqlarea.address, v$sqlarea.hash_value) IN (
  4     SELECT sql_address, sql_hash_value FROM v$session
  5         WHERE SID IN (SELECT SID FROM v$session a, x$kglpn b
  6                   WHERE a.saddr = b.kglpnuse AND b.kglpnmod <> 0
  7               AND b.kglpnhdl IN (SELECT p1raw FROM v$session_wait
  8                                             WHERE event LIKE 'library%')));
SQL_TEXT
--------------------------------------------------------------------------------
truncate table iptt_pm_all

至此,发现了导致问题的关键所在,持有pin的用户在执行truncate table iptt_pm_all的操作。

问:这个truncate是嵌在过程里面的?

答:是的,在一个loop中间的。每半个小时调用一次,类似的怎么也有10个程序吧,公用iptt_pm_all临时表。

我请求查看网友的代码,在一个Procedure中发现了大量如下语句(做了适当简化):

update iptt_pm_all p
     set n27 = (SELECT count(*)
                  FROM iptca_interface b
                 WHERE p.int_id = b.related_node
                   AND b.iftype = 18
                   AND b.IFOPERSTATUS IN (1,5));
 
 insert into iptt_pm_all (col_time, int_id, ipaddr,
                n1, c1, n2, c2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16,
                n17, n18, n19, n20, c3, n21, c4, n22, c5, n23, n24, n25, n26, n27)
         select compress_day, int_id, object_ip_addr, ……………..
           from iptaws_gwgj_hour
          where compress_day = v_time.col_time;
 
 SELECT col_time,n21,c4,n22,
         c5,n1,c1,n2,c2,
         sum(n3),sum(n4),sum(n5),sum(n7),sum(n8),sum(n9),
         sum(n10),sum(n11),sum(n12),sum(n13),sum(n14),
         sum(n16),sum(n17),sum(n18),sum(n19),sum(n20)
    FROM iptt_pm_all
   GROUP BY col_time,n21,c4,n22,c5,n1,c1,n2,c2;
 
  v_dsql := 'truncate table iptt_pm_all';
  EXECUTE IMMEDIATE v_dsql;

类似的存储过程还有很多。我请求获取Shared Pool的转储文件用于分析,Level 32级。

ALTER SESSION SET EVENTS 'immediate trace name LIBRARY_CACHE level 32';

限于篇幅,这里不再列举dump文件内容,需要注意的是,在生产环境上使用以上命令应该十分慎重。如果Shared Pool很大,转储文件可能非常巨大,而且可能引发性能问题和Bug。

根据trace文件及MetaLink说明,最终发现问题是由于truncate临时表时不适当地请求了排他锁所致,理论上truncate临时表无需排他锁定,但是Oracle使用了与处理常规表同样的方式处理临时表的锁定,从而导致了Library Cache Pin和Library Cache Lock的竞争,而且该问题并未作为Bug修正。由于该问题主要当多户交叉访问时引起,所以建议对于不同用户改用独立的临时表,此问题就可得以避免。


「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论