一個Oracle會話嚴重阻塞的案例

 環境:sql

  os rhel 5.3
  dbms 三節點 Oracle 10g rac
  ver  10.2.0.4
現象:
    某些工做站死機或網絡異常後,特定的收費人員在ZLHIS中收費時,點擊肯定後,程序無響應.將會話kill後,從新登陸ZLHIS,再次收費現象依舊.不管普通病人,仍是醫保病人都是一樣現象.1-2小時後,ZLHIS自動恢復正常.
分析與解決過程:
  1.分析會話的狀態:
經過查詢找出會話的等待事件:

SQL> select  event,sid,serial# ,blocking_session from gv$session where username='YB040';服務器

EVENT                                                                   SID    SERIAL# BLOCKING_SESSION網絡

---------------------------------------------------------------- ---------- ---------- -------------session

SQL*Net message from client                                             972      48797併發

SQL*Net message from client                                            1069      61575ide

SQL*Net message from client                                            1111      12404高併發

enq: TX - row lock contention                                          1171      55482             1069測試

enq: TX - row lock contention                                          1113      42042             1069ui

 
能夠看到是1069阻塞了1171與1113會話,等待事件爲enq: TX - row lock contention,典型的tx行級鎖,查看1069會話鎖定的對象:

  說明: http://bbs.zlsoft.com/data/p_w_upload/album/201102/25/103110ccqghgpxgt15pqgu.jpg

     分析一下業務,只有鎖定了人員繳款餘額,纔有會這種現象,由於指定收費員的特定結算方式佔用一行數據,而每次收費時都須要更新這一行數據,這一行數據就容易造成tx事務鎖,一旦一個會話持有這一行的tx鎖,其餘會話將沒法繼續收費。
通常狀況下,tx等級鎖,只有事務提交或回退,或者kill掉會話,事務也會自動回退.但這個案例中,kill掉會話也不行。
取出這個時段的awr報告,發現tx鎖的等待排在首位:

  說明: http://bbs.zlsoft.com/data/p_w_upload/album/201102/25/1031105xf58fqex559q9ez.png

平均等待時間也達到489ms,已經很是嚴重了。查詢了一下這個表的物理佔用狀況,一個只有471行的表,竟然佔用了24個數據塊:

說明: http://bbs.zlsoft.com/data/p_w_upload/album/201102/25/103110a2r6rlj37kqbdd88.jpg

   2.分析表的數據分佈
    這是不正常的.Dump這個表的全部數據塊,使用以下命令:

alter system dump datafile 7 block min 577033 block max  5770573d

 發現一些問題:
a. 數據分佈不均勻,大多數數據塊只存儲了10-33行數據.而大多數行存儲在兩個主要的塊中,這經過nrow能夠看到:

data_block_dump,data header at 0x13045264

===============
tsiz: 0x1f98
hsiz: 0x34
pbl: 0x13045264
bdba: 0x01c8ce0c
     76543210
flag=--------
ntab=1
nrow=17
frre=-1
fsbo=0x34
fseo=0x12d5
avsp=0x1d9d
tosp=0x1d9d
 
較密的塊:

data_block_dump,data header at 0x130453b4

===============
tsiz: 0x1e48
hsiz: 0x254
pbl: 0x130453b4
bdba: 0x01c8ce0e
     76543210
flag=--------
ntab=1
nrow=289
frre=193
fsbo=0x254
fseo=0x261
avsp=0xd
tosp=0xd 
   標註爲紅色的nrow項目,表示這一個數據塊中包括多少行數據,在繳款餘額這張表上,存在大量的update,併發事務也很是高,若是數據集中在少數的數據塊上,必然加重熱點塊的併發爭用。
    b.  出現了行連接現象:
行頭的內容:
tab 0, row 74, @0x16ff

tl: 9 fb: --H----- lb: 0x0  cc: 0

nrid:  0x01c8ce0d.1f
行尾的內容:

tab 0, row 31, @0x7f0

tl: 32 fb: ----FL-- lb: 0x2  cc: 4

hrid: 0x01c8ce0e.4a

   dump文件中,項目fb是一串標誌位, --H-----表示只有行頭; ----FL—表示有行的第一片斷和最後一片斷,完整的fb標誌列的說明以下(來源於Oracle的DSI文檔):

說明: http://bbs.zlsoft.com/data/p_w_upload/album/201102/25/103110ybqyvkn8o8kyfye8.png

這樣一個小表出現這種狀況是不正常的,由於平均行長很小,只能是大量的update致使了這樣的現象。 
c.數據密度較大的塊上的空閒空間不足,以上塊爲例:avsp=0xd,項目 avsp表示塊中的可用空閒空間,這裏轉換成10進製表求只有13個字節可用。
再來看看itl的狀況:

 Block header dump:  0x01c8ce0e

 Object id on Block? Y

 seg/obj: 0x13485  csc: 0x00.2bcd2f5e  itc: 16  flg: E  typ: 1 - DATA

     brn: 0  bdba: 0x1c8ce09 ver: 0x01 opc: 0

     inc: 0  exflg: 0

 
 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc

0x01   0x0025.00a.00004f48  0x09819c74.0218.33  C---    0  scn 0x0000.2bcd26e6

0x02   0x000a.016.0002e06b  0x008015d3.614f.07  C---    0  scn 0x0000.2bcd297e

0x03   0x0009.003.0000fb75  0x00800602.2faf.06  C---    0  scn 0x0000.2bcd253f

0x04   0x0001.02a.0000bd22  0x0080230b.28d3.48  --U-    1  fsc 0x0000.2bcd2fce

0x05   0x0005.00b.0000bd6a  0x00801d86.2831.35  C---    0  scn 0x0000.2bcd224a

0x06   0x0036.017.000236cf  0x09c23f51.04e2.2c  C---    0  scn 0x0000.2bcd25c7

0x07   0x0026.011.00004eef  0x0980083f.023c.4b  C---    0  scn 0x0000.2bcd2dcc

0x08   0x0036.01d.000236d5  0x09c23f5b.04e2.31  C---    0  scn 0x0000.2bcd2a26

0x09   0x0026.004.00004ef3  0x09800839.023c.06  C---    0  scn 0x0000.2bcd280d

0x0a   0x000a.01d.0002e058  0x008015d2.614f.3a  C---    0  scn 0x0000.2bcd2579

0x0b   0x000a.009.0002e054  0x008015ce.614f.41  C---    0  scn 0x0000.2bcd23b8

0x0c   0x000a.00f.0002e063  0x008015d3.614f.33  C---    0  scn 0x0000.2bcd2c20

0x0d   0x002d.004.00004cef  0x09c2237c.0266.0c  C---    0  scn 0x0000.2bcd2d07

0x0e   0x0031.00b.00004cf6  0x09c23ffe.0296.04  C---    0  scn 0x0000.2bcd2336

0x0f   0x0028.007.00004fa5  0x0981d616.0216.3d  --U-    1  fsc 0x0000.2bcd319b

0x10   0x0036.00f.000236cb  0x09c23f63.04e2.2b  --U-    1  fsc 0x0000.2bcd2f72

    擴展一個itl須要大約23字節的空間,目前數據塊已經擴展到16個itl槽,而初始的initrans爲10,可見因爲空閒空間缺少,致使事務一直沒法提交或回退,只有等到整個併發事務下來了,可以取得itl的時候就能夠繼續事務了,因爲醫院的高峯期要的高併發狀態要持續一段時間,致使會話一直沒法取得itl,只一直等下去。Itl不足是致使這個現象的一個緣由。咱們須要重建繳款餘額這個表,使用move表的方法,但須要注意的是move表後,須要重建表上的索引:

     alter table 人員繳款餘額 pctfee 20 inittrans  40 ;

     alter table  人員繳款餘額 move;

     alter index 人員繳款餘額_PK rebuild pctfree 20 initrans 40 ;

    4. 但還有一個問題,爲何kill掉會話,會話也不釋放tx事務鎖資源呢?Oracle由PMON進程來釋放殭屍會話的鎖、變量等資源,但這須要一個時間;這就是後面開啓的會話等待1-2個小時,自動復活的緣由。Oracle 有一個Dead Connection Detection(DCD 殭屍進程檢測)的功能,啓用這個功能後,Oracle會在指定的空閒間隔時間內,發送一個10個字節的探測包,若是客戶端進程無響應則會啓用PMON後臺進程對這個進程的所佔用的相關資源進程清理操做,包括內存資源(如PGA,UGA)、變量、鎖等進行釋放。
我在測試的rac環境,實驗過這個方案。具體實施方法也很是簡單:
 A  .在每一個服務器節點的sqlnet.ora文件中添加這個參數:
SQLNET.EXPIRE_TIME= <# of minutes>
 
這個參數就是指定的空閒時間,也就是探測包發送的空閒間隔時間,以分鐘爲單位,可根據實際狀況,設置一個時間。.
 B. 設置這個參數後,要求重啓或reload監聽程序,因爲重啓監聽程序不影響已經鏈接的用戶,能夠直接重啓;因爲是rac環境,須要重啓全部節點的監聽程序;若是是RAC環境,在任一節點執行以下命令便可:

  srvctl stop listener –n 節點名

  srvctl start listener –n 節點名

 進行了這些調整後,系統運行了2個星期,沒有再出現這個問題。
相關文章
相關標籤/搜索