Pages

14 Nisan 2011 Perşembe

Oracle veritabanında kuyruğa ekleme(enqueue) olayları - Bölüm 2

Çeşitli tipte kuyruğa ekleme tipleri olmasından dolayı, bir kuyruğa ekleme bekleme olayı farklı sebeplerden meydana gelebilir. Yaygın sebepler ve bunlara karşı alınacak olan önlemler, farklı oturumlar tarafından çekişme yaşanan kuyruk ekleme tipine ve moduna göre değişmektedir. Oracle, her bir kuyruk ekleme tipi için X$KSQST yapısı içinde istek sayısı ve beklemelerin instance seviyesinde istatistiğini tutar.

select *
from   v$enqueue_stat
where  cum_wait_time > 0
order by inst_id, cum_wait_time;

   INST_ID EQ TOTAL_REQ# TOTAL_WAIT#  SUCC_REQ# FAILED_REQ# CUM_WAIT_TIME
---------- -- ---------- ----------- ---------- ----------- -------------
         1 SQ      66551         437      66551           0           498
         1 CU      64353         133      64353           0          1616
         1 HW     453067       18683     453067           0         11811
         1 CF     119748          76     119605         143         37842
         1 TX   22687836        9480   22687758          71        672435
         1 TC       3620         724       3620           0        679237
         1 TM   89822967          91   89817200           5       4056333

Yukardaki alınan sonuç ile kullanıcıların hangi tip ve modda kuyruğa ekleme beklemeleri ile yüzyüze kaldığını tespit edebilirsiniz. Can acıtan nokta, kullanıcılar bu beklemeler sebebiyle herhangi bir hata mesajı almazlar ve oturumları donar. Zaten, arandığınızda söylenende oturumların ansızın donduğu ve cevap vermediği şeklindedir.

Tüm kuyruğa eklemeler hakkında detaya girmeyeceğim, çünkü bir kısmının gereksiz olduğunu düşünüyorum. Ancak, en sık ve yaygın karşılaşılan kuyruğa ekleme beklemelerine detaylı olarak aşağıda odaklanacağım.

Mod 6 TX kuyruğa ekleme bekleme olayı
Mod 6 TX kuyruğa ekleme beklemesi(P1= 1415053318, P1RAW= 54580006) en yaygın karşılaşılan kuyruğa ekleme bekleme olayıdır(Oracle Database 10g itibariyle enq: TX—row lock contention.) Bu bekleme olayı satır seviyesinde çakışma olduğuna işaret eder. Bu beklemeye olayı, satırlar bir işlem için kilitlendiği zaman, bu esnada başka bir işlemin aynı satırlara güncelleme veya silme işlemi yapmaya çalışmasında meydana gelir. Bu genellikle program tabanlı bir hatadır. Bu durumda bekleyen oturum, bloklayan oturumun işlemi için işleme(commit) veya geri alma(rollback) yapana kadar bekleyecektir. Kilidi, bloklayan oturumun sonlandırılması dışında, serbest bırakacak başka bir yol yoktur. Tabii, eğer bu bloklayan oturum sonlandırılırsa(kill) yaptığı işlem geri alınacak ve bu işleme bağlı girişlerde ortadan kalkacaktır. Bu genelde istenmez. Aşağıdaki liste mod 6 TX kuyruğa ekleme beklemesi için bir örnektir.

ADDR     KADDR    SID TY    ID1    ID2 LMODE REQUEST CTIME BLOCK
-------- -------- --- -- ------ ------ ----- ------- ----- -----
A3950688 A395069C  10 TM 188154      0     3       0     3     0
A304E2A0 A304E2B0  10 TX  65585 147836     0       6     3     0
01AD23D4 01AD24A4  20 TX  65585 147836     6       0    10     1
A3950A28 A3950A3C  20 TM 188154      0     3       0    10     0


Ne zaman TX kuyruğa eklemesine bağlı bir bekleme olayı görülürse, ilk adım aşağıdaki sorguyu kullanarak, kimin blokladığını tespit etmek ve aynı kaynak için başka bekleyenlerin olup olmadığını görmektir. Eğer bloklayan oturum bir ad-hoc prosesi ise, o zaman bu kullanıcı bir mola verebilir. Bu durumda, bu bloklayan kullanıcının işleme(commit) veya geri alma ile kaynağı serbest bırakmasını talep edebilirsiniz.  Eğer bloklayan bir OLTP uygulama prosesi veya batch ise, bu durumda oturumun hala aktif olup olmadığını kontrol edebilirsiniz. Eğer aktif bir oturumsa, bu durumdada alt proseslerinin ölü veya askıda olup olmadığını kontrol edebilirsiniz.

select /*+ ordered */
       a.sid         blocker_sid,
       a.username    blocker_username,
       a.serial#,
       a.logon_time,
       b.type,
       b.lmode       mode_held,
       b.ctime       time_held,
       c.sid         waiter_sid,
       c.request     request_mode,
       c.ctime       time_waited
from   v$lock b, v$enqueue_lock c, v$session a
where  a.sid     = b.sid
and    b.id1     = c.id1(+)
and    b.id2     = c.id2(+)
and    c.type(+) = ’TX’
and    b.type    = ’TX’
and    b.block   = 1
order by time_held, time_waited;

Ayrıca, çekişme yaşanan kaynağı ortaya çıkarabilirsiniz. Kaynak  ID bilgisi, bu işlem için DML kilidinin(TM) V$LOCK.ID1 kolonunda yer almaktadır. Ayrıca, bekleyen oturumun V$SESSION.ROW_WAIT_OBJ#  kolonundada bu bilgi yer alır. Aşağıdaki sorgu, TX kuyruğa ekleme bekleme olayının kaynağını listelemektedir.

select c.sid waiter_sid, a.object_name, a.object_type
from   dba_objects a, v$session b, v$session_wait c
where  (a.object_id = b.row_wait_obj# or
        a.data_object_id = b.row_wait_obj#)
and    b.sid       = c.sid
and    chr(bitand(c.P1,-16777216)/16777215) ||
       chr(bitand(c.P1,16711680)/65535) = ’TX’
and    c.event     = ’enqueue’;

Bununla beraber, bekleyen oturum tarafından çalıştırılan SQL komutu ile birlikte bloklayan oturum tarafından çalıştırılan SQL komutunuda ekstrakt ederek, hem bloklayan oturumun, hemde bekleyen oturumun ne tür bir işlem yaptığı hakkında detaylı bir fakir sahibi olabiliriz. Bu SQL komutlarının incelenmesi sonucunda, uygulama geliştiriciler hangi modüllerin çakışmalara sebep olduğunu teşhis edebilecek ve ilgili modüllerde düzeltici işlemler yapılabilecektir. 

Mod 4 TX kuyruğa ekleme bekleme olayı - ITL eksikliği
Mod 4 TX kuyruğa ekleme bekleme olayı genellikle aşağıdaki sebeplerden birisi yüzünden meydana gelmektedir.

·        Yetersiz blok alanı ve ITL (ilgili işlem listesi) eksikliği
·        Farklı oturumlar tarafından aynı tekil(unique) anahtarın yazılması
·        Bitmap indeks girişi

Bu bekleme olayına, bir veri bloğunda işlem yuvası olan ITL(İlgili İşlem Listesi) ile başlayacağım. ITL yuvalarının başlangıç sayısı INITRANS cümleciği tarafından tanımlanır ve MAXTRANS cümleciği ile sınırlandırılır. Varsayılan olarak, bir tablonun 1 ITL ve bir indeksin 2 ITL’i vardır. Her bir ITL 24 bytes ile çalışmaya başlar ve  USN.SLOT#.WRAP#. formatı içinde işlem ID’sini içerir. Oracle 10g ile bu bekleme olayı, enq: TX—allocate ITL entry olarak yeniden adlandırılmıştır.

Veri değişikliğe uğramanda önce, her DML işlemi blok içindeki kendi ITL alanını elde eder. Bu ITL için çakışma olayı blok içindeki tüm uygun ITL’ler halihazırda kullanımda olduğunda(yani MAXTRANS değerine erişildiğinde) ve Oracle için dinamik olarak yeni bir ITL yuvası tahsisi için PCTFREE alanında yeterli alan kalmadığında meydana gelir.  Bu durumda, işlemlerden birisi işlenmeden(commit) veya geri alınmadan(rollback)  oturum bekleyecek ve bu ITL yuvasını tekrar kullanacaktır. ITL bir alışveriş merkezinin otopark alanı gibidir. Alışveriş merkezine arabasıyla gelen her müşteri boş park yeri arar, eğer otopark alanında boş yer yoksa birisi otoparktan çıkana kadar otopark alanı etrafında bulmak umuduyla turlar.

ITL yetersizliği sebebiyle oluşan Mod 4 TX kuyruğa ekleme bekleme olayı için bir örnek yer almaktadır.

ADDR     KADDR    SID TY    ID1    ID2 LMODE REQUEST CTIME BLOCK
-------- -------- --- -- ------ ------ ----- ------- ----- -----
8A2B6400 8A2B6414   8 TM   3172      0     3       0   248     0
89EF3A0C 89EF3A1C   8 TX 131147     13     0       4   248     0
01A4177C 01A41848   9 TX 131147     13     6       0   376     1
8A2B6388 8A2B639C   9 TM   3172      0     3       0   376     0

Mod 4 TX kuyruğa ekleme bekleme olayı her zaman ITL yetersizliği sebebiyle oluşmaz. Bekleyen oturumun V$SESSION satırı kuyruğa ekleme nesnesi hakkında bilgi içermektedir. Kolonlar  ROW_WAIT_FILE# ve ROW_WAIT_BLOCK# ‘dir. Bu değerleri kullanarak bloğun içeriğini görüntüleyebilir, blok içindeki aktif ITL sayısını(--U--) görebilir ve böylece sorunun ITL’den kaynaklanıp kaynaklanmadığına karar verebiliriz. Eğer sorun ITL’den kaynaklanıyorsa, bu objeye ait segment daha yüksek bir INITRANS değeri ile veya daha yüksek bir PCTFREE değeri ile yeniden oluşturularak sorun çözülür.

alter system dump datafile <file#> block <block#>;

Alttaki örnekte ,blok içeriğinde görüntülenen ITL kullanan bölüm kırmızı 2 satırda yer almaktadır. Yani INITRANS değerinden 2 ITL kullanılmış, 2 ITL ise daha kullanılmamıştır (C--)

 Itl         Xid                      Uba   Flag  Lck        Scn/Fsc
0x01 0x000a.051.0001fcf2 0x07ca2145.4e11.18 --U-    0  scn 0x070e.03df2f08
0x02 0x0005.049.00022d46 0x090618b7.5967.1c C---    0  scn 0x070e.03df2f6a
0x03 0x0012.008.0001244b 0x0580a510.26ac.0c --U-    0  scn 0x070e.03df2f7b

0x04 0x0014.00d.00012593 0x090d4f93.28d3.1e C---    0  scn 0x070e.03e08919


Oracle 9i itibariyle nesne bazlı ITL bekleme sayısı izlemeleri saklanmakta ve V$SEGMENT_STATISTICS görünümünde bu bilgi yayınlanmaktadır. Veritabanındaki önemli ITL beklemelerini görmek için aşağıdaki sorgu kullanılabilir:

select owner,
       object_name,
       subobject_name,
       object_type,
       tablespace_name,
       value,
       statistic_name
from   v$segment_statistics
where  statistic_name = ’ITL waits’
and    value > 0
order by value;


Mod 4 TX kuyruğa ekleme bekleme olayı - Tekil Anahtar Kullanımı
Tekil veya birincil anahtar kullanımı Mod 4 TX kuyruğa ekleme bekleme olayının diğer bir sebebidir. Oracle 10g itibariyle bu bekleme olayının adı enq: TX—row lock contention olmuştur.  Bu bekleme olayı bir veya birden fazla tekil anahtar kısıtlaması içeren bir tabloya, bir çok oturumun eşzamanlı olarak aynı değeri girmesiyle meydana gelir. İlk oturum değeri başarıyla girer, ancak “ORA-00001 unique constraint (%s.%s) violated” hatası alınmasıyla beraber geri kalanların işlemi donar ve ilk oturum işleme(commit) veya geri alma(rollback) yapana kadar geri kalanlar bekler.

Aşağıdaki örnekte görüldüğü gibi, tekil anahtar kullanımı sebebiyle oluşan Mod 4 TX kuyruk ekleme beklemesi V$LOCK görünümünde listelenmiştir. Peki o zaman tekil anahtra kullanımı ve ITL yetersizliği arasındaki farklılık nedir?

SID=8 olan bekleyenin iki tane TX girişi olduğuna dikkat edin. Bu demek değildirki SID=8, iki tane işleme sahiptir. Aslında, V$TRANSACTION sadece iki adet işlem göstermektedir, birisi SID 8’e ait, diğeri ise SID 9’a ait. Aşağıdaki liste bize, SID 8’in, SID 9 tarafından tutulan TX kilidini beklediğini göstermektedir ve SID 8, nesne üzerinde paylaşımlı kilidi(Mod 4) talep etmektedir. SID 8, aynı zamanda kendi işlemi içinde TX kilidi tutmaktadır. Bunun yanında, her zaman DML işleminin ID1’inde kayıtlı nesne ID’sinde dikkat edilmesi gereken nokta,-tekil anahtarın indeks üzerinde zorlanmasına rağmen- tablo ID’sidir, indeks ID’si değil. BLOCK kolonunda 1 değeri bloklayan, 0 değeri olan ise bekleyendir.


ADDR     KADDR    SID TY    ID1   ID2 LMODE REQUEST CTIME BLOCK
-------- -------- --- -- ------ ----- ----- ------- ----- -----
01AF6120 01AF61EC   8 TX 131099    14     6       0  4051     0

8A2B6388 8A2B639C   8 TM   3176     0     3       0  4051     0
89EF37CC 89EF37DC   8 TX 131094    14     0       4  4051     0
01AF6120 01AF61EC   9 TX 131094    14     6       0  4461     1
8A2B6400 8A2B6414   9 TM   3176     0     3       0  4461     0

Bunun yanında kimin kimi blokladığını net şekilde raporlamakta mümkündür.

SQL> select s1.username || '@' || s1.machine
 || ' ( SID=' || s1.sid || ' )  is blocking '
 || s2.username || '@' || s2.machine || ' ( SID=' || s2.sid || ' ) ' AS blocking_status
 from v$lock l1, v$session s1, v$lock l2, v$session s2
 where s1.sid=l1.sid and s2.sid=l2.sid
 and l1.BLOCK=1 and l2.request > 0
 and l1.id1 = l2.id1
 and l2.id2 = l2.id2 ;


BLOCKING_STATUS
-----------------------------------------------------------------
trant12@antnb201 ( SID=9 )  is blocking trant43@antnb162 ( SID=8 )

Alınacak eylemler daha önce açıkladığım Mod 6 ile aynıdır; kimin blokladığını tespit etmek, hangi kaynak için çakışma yaşandığını bulmak, bekleyen ve bloklayan oturumların çalıştırdığı SQL komutlarının yapısını incelemek... Bu sorun, uygulama katmanında yaşanan bir sorundur ve kullanılan uygulama içerisinden uygulama geliştiriciler tarafından düzeltilmelidir.


Mod 4 TX kuyruğa ekleme bekleme olayı - Bitmap indeks girişi
Mod 4 TX kuyruğa ekleme bekleme olayı ayrıca, bitmap girişi tarafından kapsanmış değişik satırların bir çok oturum tarafından güncellenme veya silinme denemelerinde oluşabilir. Uygulama, bitmap indeksler kullanmıyorsa bu bekleme olayıda olmaz.

Tekil ROWID içeren B-tree indeks girişlerinden farklı olarak, bir bitmap girişi geniş ROWID dağılım aralığını kapsar. Böylece bir bitmap indeksi kilitlendiğinde, giriş tarafından kapsanan tüm ROWID lerde kilitlenir.

Aşağıdaki örnekte, bitmap girişi sebebiyle meydan gelen mod TX bekleme olayı V$LOCK görünümünden elde edilmektedir. Peki, aşağıdaki çıktının yukardaki tekil anahtar kullanımı örneğinden ne farkı vardır?

V$LOCK görünümü sonucuna bakarak Mod 4 TX kuyruk ekleme bekleme olayının bitmap indeks girişindenmi, yoksa tekil anahtar kullanımındanmı kaynaklandığı anlaşılırmı? Bunun cevabı HAYIR’dır. TM kilidindeki obje ID’side, tablonun obje ID’si olduğundan dolayı yardımcı olamaz. İşte bu sebeple, bloklayan ve bekleyen oturumların SQL komutlarını yakalamak ve bunlara bakmak önem kazanmaktadır.  Eğer bekleyen oturum INSERT işlemi yapıyorsa, o zaman tekil anahtar kullanım sorunu yaşanmaktadır.  Eğer bekleyen oturum UPDATE veya DELETE işlemi yapıyorsa, büyük ihtimalle bitmap giriş sorunu yaşanmaktadır.

ADDR     KADDR    SID TY    ID1   ID2 LMODE REQUEST CTIME BLOCK
-------- -------- --- -- ------ ----- ----- ------- ----- -----
01A52DB4 01A52E80   7 TX 131120    14     6       0    31     1
8A2B6310 8A2B6324   7 TM   3181     0     3       0    31     0
01A52DB4 01A52E80   9 TX 131107    14     6       0     9     0
8A2B6388 8A2B639C   9 TM   3181     0     3       0     9     0
89EF3A4C 89EF3A5C   9 TX 131120    14     0       4     9     0

0 yorum:

Yorum Gönder