library cache pin

轉自:http://www.itpub.net/thread-1703738-1-1.html

最近運行一個分批刪除數據的procedure,感覺運行比較慢,臨時取消了該job,然後再次重建procedure時,sessionhang住了,應該是library cache pin的等待事件了,oracle用兩種結構pinlock來控制shared pool的併發訪問控制。

訪問一個對象將其pin到內存中,在pin之前需要先獲取該對象的handle的鎖定,lock的索引主要有nullshare exclusive,當然pin該對象也有上述三種狀態。

Session a execute delete_data

臨時取消了該procedure的運行,實際進程並沒有馬上釋放該對象的pin

Session b

SQL> create orreplace procedure delete_data

  2  as

  3 begin

  4  loop

Delete fromTEXTAUTO_FOLDERARTICLE where LASTPOSTDATE<sysdate-10 and rownum<10000;

Exit whensql%notfound;--dml語句中隱式遊標屬性進行控制

Commit;

End loop;

  9 Commit;

10  end;

11  /

出現了library cache pin等待事件:

SQL> selectevent,count(*) from v$session group by event;

EVENT                                                             COUNT(*)

--------------------------------------------------------------------------

SQL*Net messagefrom client                                             92

library cachepin                                                        1

jobq slavewait                                                          1

rdbms ipcmessage                                                       10

smon timer                                                               1

pmon timer                                                               1

db file scatteredread                                                    1

Streams AQ: qmnslave idle wait                                           1

SQL*Net message toclient                                                1

Streams AQ: qmncoordinator idle wait                                     1

Streams AQ: waitingfor time management or cleanup tasks                  1

11 rows selected.

分析一下上述的library cache pin是如何造成的:首先系統運行了該procedure,此時該對象已經被pin到內存,佔用了一個share pin和一個null lock,而此時在進程還沒有釋放此pin之前再次create procedure,此時要獲取一個exclusive pinexclusivelock,由於之前的share pinexclusivepin不共存,此時就會產生一個library cache pin等待。

這裏注意一下兩個基表x$kglpnx$kgllk,對於解決library cache pinlock太輕鬆了。

SQL> descx$kglpn;

Name                                     Null?    Type

------------------------------------------------- ----------------------------

ADDR                                              RAW(8)

INDX                                              NUMBER

INST_ID                                           NUMBER

KGLPNADR                                          RAW(8)

KGLPNUSE                                          RAW(8)

KGLPNSES                                           RAW(8)

KGLPNHDL                                          RAW(8)

KGLPNLCK                                          RAW(8)

KGLPNCNT                                          NUMBER

KGLPNMOD                                           NUMBER

KGLPNREQ                                          NUMBER

KGLPNDMK                                          NUMBER

KGLPNSPN                                          NUMBER

通過等待事件的p1raw參數聯合kglpnhdl來獲取kglpnuse,這裏的kglpnmodkglpnreqv$locklmoderequest基本相同,kglpnmod=2表示此時這個session佔有了library cache pin而造成了kglpnreq=3這個session的等待。

SQL> selectkglpnuse,kglpnhdl,kglpnmod,kglpnreq from x$kglpn where kglpnhdl in (selectp1raw from v$session where event='library cache pin');

KGLPNUSE         KGLPNHDL           KGLPNMOD  KGLPNREQ

-------------------------------- ---------- ----------

00000000D822759000000000DD876D98          0          3

00000000DA22534000000000DD876D98          2          0

聯合v$sessionsaddr來獲取sid然後可以通過v$processkill掉沒有釋放的進程。

SQL> selectb.spid,a.sid from v$session a,v$process b where a.saddr in ('00000000DA225340') and a.paddr=b.addr;

SPID                SID

----------------------

11232               195

而如果此時再重新編譯一下該procedure,同樣需要獲取一個該對象的lock鎖定,由於上述重建procedure還在視圖獲取該對象的librarycache lockexclusive lock,那麼當然此時出現librarycache lock是當然的。

SQL> alterprocedure delete_data compile;

SQL> selectevent,count(*) from v$session group by event;

EVENT                                                             COUNT(*)

--------------------------------------------------------------------------

SQL*Net messagefrom client                                             91

library cachepin                                                        1

jobq slavewait                                                           1

rdbms ipcmessage                                                       10

smon timer                                                               1

pmon timer                                                               1

db file scatteredread                                                   1

library cachelock                                                       1

Streams AQ: qmnslave idle wait                                           1

SQL*Net message toclient                                                 1

Streams AQ: qmncoordinator idle wait                                     1

SQL> descx$kgllk;

Name                                     Null?    Type

------------------------------------------------- ----------------------------

ADDR                                              RAW(8)

INDX                                              NUMBER

INST_ID                                           NUMBER

KGLLKADR                                           RAW(8)

KGLLKUSE                                          RAW(8)

KGLLKSES                                          RAW(8)

KGLLKSNM                                          NUMBER

KGLLKHDL                                          RAW(8)

KGLLKPNC                                          RAW(8)

KGLLKPNS                                          RAW(8)

KGLLKCNT                                          NUMBER

KGLLKMOD                                          NUMBER

KGLLKREQ                                           NUMBER

KGLLKFLG                                          NUMBER

KGLLKSPN                                          NUMBER

KGLLKHTB                                          RAW(8)

KGLNAHSH                                           NUMBER

KGLLKSQLID                                        VARCHAR2(13)

KGLHDPAR                                          RAW(8)

KGLHDNSP                                          NUMBER

USER_NAME                                         VARCHAR2(30)

KGLNAOBJ                                          VARCHAR2(60)

獲取blocking session的方法基本相同,也是通過p1raw參數聯合kgllkhdl來獲取kgllkuse,最後聯合v$session來獲取sid,進而通過v$process獲取spid,殺掉進程後即可

SQL> selectkgllkhdl,kgllkuse,kgllkreq,kgllkmod from x$kgllk where kgllkhdl in (Selectp1raw from v$session where event='library cache lock');

KGLLKHDL         KGLLKUSE           KGLLKREQ   KGLLKMOD

-------------------------------- ---------- ----------

00000000DD876D9800000000DA225340          0          1

00000000DD876D9800000000D8227590          0          3

00000000DD876D9800000000D821FC40          3          0

通過上述的library cache pinlibrary cache lock等待事件的分析和診斷,可以看出數據字典基表可以提供我們非常的信息,而幫助解決一些比較棘手的案例,當然上述我們也可以利用oradebug然後通過trace文件來診斷,不過相對trace文件較難以閱讀,需要一定的功底,後續如果有對該等待事件trace的解決案例再拿出來與大家分享。


轉自:http://www.xifenfei.com/3172.html

library cache pin說明
library cache pin 事件是用來管理library cache的併發訪問的, pin一個object會引起相應的heap被載入內存中,如果客戶端需要修改或檢測這個object它就必須在鎖住後取得一個pin.library cache pin的等待時間爲3秒鐘,其中有1秒鐘用於PMON後臺進程,即在取得pin之前最多等待3秒鐘,否則就超時.library cache pin通常是發生在編譯或重新編譯PL/SQL,VIEW,TYPES等object時.編譯通常都是顯性的,如安裝應用程序,升級,安裝補丁程序等,但object的重新編譯也可能發生在object變得無效時.library cache pin的參數如下,有用的主要是P1和P2:
P1 – KGL Handle address.
P2 – Pin address
P3 – 10*Mode + Namespace
其中,P1,P2可與x$kglpn和x$kglob表相關.x$kglpn和x$kglob是ORACLE數據庫的內部數據字典.
x$kglpn library cache pin信息
x$kglob library cache object信息

查詢方法一

--通過查詢V$SESSION_WAIT找出正在等待”library cache pin”的session
SELECT sid,
       SUBSTR (event, 1, 30),
       TO_CHAR(p1, 'xxxxxxxx') p1_16,
       --P1RAW P1_16,
       p2,
       p3
  FROM v$session_wait
 WHERE wait_time = 0 AND event LIKE 'library cache pin%';
--P1 列是Library Cache Handle Address
--P2 列是Library Cache Pin Address.
 
--找到相關session pin狀態
SELECT ADDR,
       INDX,
       KGLPNADR,-- Library Cache Pin Address
       KGLPNUSE,
       KGLPNSES,--識別鎖住此pin 的session
       KGLPNHDL,--Library Cache Handle Address
       kGLPNLCK,
       KGLPNMOD,-- Pin 鎖
       KGLPNREQ-- Pin 請求
  FROM x$kglpn
 WHERE KGLPNHDL LIKE '%EB3EB8%';--p1_16
  
 --詢X$KGLOB (Library Cache Object),可找到相關的object
SELECT KGLNAOBJ-- 相關object的名字(取前面80個字符)
  FROM X$KGLOB
 WHERE KGLHDADR LIKE '%EB3EB8%';--p1_16
  
 --查出佔着pin鎖的session目前正在做什麼
SELECT a.sid, a.username, a.program
  FROM v$session a, x$kglpn b
 WHERE a.saddr = b.kglpnuse AND b.kglpnhdl LIKE '%EB3EB8%'--p1_16
  AND b.kgnmod <> 0;
   
   --查出阻塞者正執行的SQL語句
 SELECT sid, sql_text
  FROM v$session, v$sqlarea
 WHERE v$session.sql_address = v$sqlarea.address AND sid =&sid;

查詢方法二

--通過查詢DBA_LOCK_INTERNAL和V$SESSION_WAIT,可得到與”library cache pin” 等待相關的object的名字
SELECT TO_CHAR (SESSION_ID, '999') sid,
       SUBSTR (LOCK_TYPE, 1, 30) TYPE,
       SUBSTR (lock_id1, 1, 23) Object_Name,
       SUBSTR (mode_held, 1, 4) HELD,
       SUBSTR (mode_requested, 1, 4) REQ,
       lock_id2 Lock_addr
  FROM dba_lock_internal
 WHERE mode_requested <> 'None' AND mode_requested <> mode_held
       AND session_id IN
              (SELECT sid
                 FROM v$session_wait
                WHERE wait_time = 0 AND event LIKE 'library cache pin%');
                 
 --查出”library cache pin”佔有者(即阻塞者)的session id
 SELECT sid Holder,
       KGLPNUSE Sesion,
       KGLPNMOD Held,
       KGLPNREQ Req
  FROM sys.x$kglpn, v$session
 WHERE KGLPNHDL IN (SELECT p1raw
                      FROM v$session_wait
                     WHERE wait_time = 0 AND event LIKE 'library cache pin%')
       AND KGLPNMOD <> 0
       AND v$session.saddr = x$kglpn.kglpnuse;
        
 --查出”library cache pin”佔有者(阻塞者)正在等什麼
 SELECT sid, SUBSTR (event, 1, 30), wait_time
  FROM v$session_wait
 WHERE sid IN
          (SELECT sid
             FROM x$kglpn, v$session
            WHERE KGLPNHDL IN
                     (SELECT p1raw
                        FROM v$session_wait
                       WHERE wait_time = 0
                             AND event LIKE 'library cache pin%')
                  AND KGLPNMOD <> 0
                  AND v$session.saddr = x$kglpn.kglpnuse);
                   
 --查出阻塞者正執行的SQL語句
 SELECT sid, sql_text
  FROM v$session, v$sqlarea
 WHERE v$session.sql_address = v$sqlarea.address AND sid =&sid;

發佈了47 篇原創文章 · 獲贊 8 · 訪問量 23萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章