Constraint Disable-Enable


Disable Constraint


BEGIN
  FOR c IN
  (SELECT c.owner, c.table_name, c.constraint_name
   FROM user_constraints c, user_tables t
   WHERE c.table_name = t.table_name
   AND c.status = 'ENABLED'
   AND NOT (t.iot_type IS NOT NULL AND c.constraint_type = 'P')
   ORDER BY c.constraint_type DESC)
  LOOP
    dbms_utility.exec_ddl_statement('alter table "' || c.owner || '"."' || c.table_name || '" disable constraint ' || c.constraint_name);
  END LOOP;
END;
/




Enable Constraint

BEGIN
  FOR c IN
  (SELECT c.owner, c.table_name, c.constraint_name
   FROM user_constraints c, user_tables t
   WHERE c.table_name = t.table_name
   AND c.status = 'DISABLED'
   ORDER BY c.constraint_type)
  LOOP
    dbms_utility.exec_ddl_statement('alter table "' || c.owner || '"."' || c.table_name || '" enable constraint ' || c.constraint_name);
  END LOOP;
END;
/

Minimizing System Contention ( 22- Oracle Enterprise Manager'dan "Waits" İncelemesi )


Oracle Enterprise Manager'dan "Waits" İncelemesi


  - OEM arabirimi, SQL komut dosyalarını çalıştırmak yerine veritabanınızdaki mevcut beklemeleri hızlı bir şekilde analiz etmenizi sağlar. Giriş sayfasında, Active Sessions grafiği, waits durumuna göre I/O ve CPU miktarlarını gösterir.
 Active session grafiğini görüntülemek için bu grafikte "waits" linkini tıklayın. Grafiğin sağ tarafında, Concurrency, Application, Cluster, Administrative, User I/O, vb. gibi çeşitli bağlantıları göreceksiniz.
Bu bağlantıların her birini tıklamak sizi bekleyen tüm aktif oturumları gösteren bir sayfaya götürecektir.
Wait class ın en önemlileri olan wait eventleri burada özetliyoruz:
 
User I/O: Bu,  db file scattered read, db file sequential read, direct path read, direct path write, and read by other gibi bekleme olaylarını gösterir.
Bekleme olaylarının bir grafiğini almak için çeşitli beklemeler içinde herhangi bir bağlantıyı tıklayabilirsiniz.
Örneğin, "db file scattered read" bağlantısını tıklattığınızda "Wait Event: db file scattered read" sayfası için histograma yönlendirilirsiniz. 
 
System I/O: Bu, db file parallel write, log file parallel write, control file parallel write ve control file sequential read wait events nedeniyle bekler.
     
Application: Bu, enqueue locks gibi olayları bekleyen active sessionsı gösterir.
 
 
  Nasıl Çalışır:
 
  -  Oracle Wait Interface'in arkasındaki teoriyi anladıktan sonra, veritabanınızdaki mevcut bekleme olaylarını hızla analiz etmek için OEM kullanabilirsiniz. Sadece hangi bekleme olaylarının performansı olumsuz etkilediğini değil, aynı zamanda hangi SQL deyiminin ve hangi kullanıcıların dahil edildiğini de öğrenebilirsiniz.
Active session sayfasından ayrıntılı bilgi alabileceğiniz tüm ayrıntılar sayfasında, instance başladığı andan itibaren belirli wair event class ın bir grafiği gösterilir. Sayfada, Top SQL ve Top Users adlı tablolar da bulunur ve bu bekleme olayından hangi SQL ve kullanıcıların etkilendiğini tam olarak gösterir.

Minimizing System Contention ( 21- Oracle Enterprise Manager üzerinden Locks Yönetimi )

Oracle Enterprise Manager üzerinden Locks Yönetimi


  - Hızlı kaybolan locking event olaylarını tanımlamak için birden fazla SQL sorgusu vermek yerine kilitleme durumlarını belirlemek ve çözmek için Oracle Enterprise Manager (OEM) DB Kontrolünü kullanabilirsiniz.
Instance üzerinde, blocking ve blocked sessionlar dahil tüm mevcut kilitleri bulabilirsiniz. Blocking sessionı OEM'den de kill edebilirsiniz.
 
  - OEM aracılığıyla locking sorunlarını yönetmenin yolları şunlardır:
   • Home page de DB Control, Alerts tablosunda locking bilgileri görürsünüz. Blocking sessionların tanımlamak için User Block kategorisini arayın. Aradığınız uyarı adı, "Blocking Session Count".
    Örneğin, bu alert için "Oturum 68 diğer 12 oturumu engelliyor" gibi mesaj bağlantısını tıkladığınızda, Blocking Session Count sayfasına yönlendirileceksiniz. Bu sayfadaki Alert History tablosunda, blocking and blocked sessionslarla ilgili ayrıntıları görüntüleyebilirsiniz.
    Ayrıca Ana sayfada, Related Alerts'ın altında, ADDM Performansı tablosunu bulacaksınız.
    Locking sorunları, Row Lock Waits bağlantısının varlığı ile açığa çıkar.
    Row Lock Waits sayfasına gitmek için Row Lock Waits bağlantısını tıklayın.
    Şekil 5-1'de gösterilen bu sayfa row locks için bekleyen tüm SQL deyimlerini görmenizi sağlar.






   • Ana sayfadaki Performans sekmesini tıklayarak blocking session ayrıntılarını da görüntüleyebilirsiniz.
Blocking Sessions sayfasına gitmek için Additional Monitoring Links bölümünün Altındaki, Blocking Sessions'ı tıklayın.
Blocking Sessions sayfası engellemenin yanı sıra engellenen oturumların ayrıntılarını da içerir.
Bir oturum başka birini engellediğinde enq: TX row lock contention olacaktır.
Bu sayfadaki SQL ID bağlantısını tıklatarak, blocking sessiona sebep olan SQL deyimini bulabilirsiniz.
Sayfanın sol üst tarafındaki Kill session a tıklayarak bu sayfadan blocking sessionı kill edebilirsiniz.
  
   • Ayrıca "Additional Monitoring Links" bölümünde, sizi Instance Locks sayfasına götüren bir link bulunmaktadır.
   Instance Locks sayfası, hem blocking hem de blocked sessionların oturum ayrıntılarını gösterir.
   Blocking ve blocked sessionların yürüttüğü geçerli SQL'i görüntülemek için SQL ID bağlantısını tıklatabilirsiniz.
   Locked nesnenin adını da öğrenebilirsiniz. Kill Session ı tıklayarak blocking session ı öldürebilirsiniz.
  
 
  Nasıl Çalışır:
 
  - Veritabanındaki locking davranışını analiz etmek için mutlaka birden fazla SQL komut dosyası çalıştırmanız gerekmez.
  Size çeşitli tariflerde daha önce gösterdiğimiz SQL kodu, Oracle kilitlemesinin nasıl çalıştığını açıklamak içindir.
  Her gün, yalnızca bir oturumun kimler tarafından engellendiğini ve nedenini bulmak için OEM'i kullanmanız daha pratik ve verimlidir.


Minimizing System Contention ( 20- Latch Contention )

Latch Contention


  - Şiddetli  latch contention, veritabanınızı önemli ölçüde yavaşlatabilir. Bir latch contention sorunu ile uğraşırken, belirli sorgu türlerini ve her bir beklemenin neden olduğu toplam bekleme süresini öğrenmek için aşağıdaki sorguyu çalıştırabiliriz.
 
  SQL> select event, sum(P3), sum(seconds_in_wait) seconds_in_wait
    from v$session_wait
    where event like 'latch%'
    group by event;
   
  - Önceki sorgu, bu oturum tarafından şu an için bekletilen kilitlemeleri gösterir. Tüm instance ın çeşitli kilitlemeler için beklediği süreyi bulmak için aşağıdaki SQL i çalıştırın:
  
  SQL> select wait_class, event, time_waited / 100 time_secs
    from v$system_event e
    where e.wait_class <> 'Idle' AND time_waited > 0
    union
    select 'Time Model', stat_name NAME,
    round ((value / 1000000), 2) time_secs
    from v$sys_time_model
    where stat_name not in ('background elapsed time', 'background cpu time')
    order by 3 desc;
  
   WAIT_CLASS  EVENT       TIME_SECS
   ------------ ------------------------- ----------
   Concurrency  library cache pin    622.24
   Concurrency  latch: library cache   428.23
   Concurrency  latch: library cache lock 93.24
   Concurrency  library cache lock    24.20
   Concurrency  latch: library cache pin  60.28
   …
  
 
  - Sorgudaki çıktı, Concurrency wait classın bir parçası olan  latch ile ilgili wait events bekleme olaylarını gösterir.
  - Ayrıca, burada gösterildiği gibi, lache contentionun bir sorun olup olmadığını görmek için AWR rapordaki top beş bekleme olayını görüntüleyebilirsiniz:
 
  Event       Waits  Time(s)  (ms) Time Wait Class
  ------------------------ ------------ ---------- ------- -------- ------------
  db file sequential read  42,005,780  232,838  6   73.8  User I/O
  CPU time         124,672    39.5  Other
  latch free      11,592,952  76,746   7   24.3 Other
  wait list latch free   107,553  2,088   19   0.7  Other
  latch: library cache   1,135,976  1,862   2   0.6  Concurrency
 
 
  - En yaygın Oracle latch wait türleri :
  
   - Shared pool ve library latches: Bunların çoğu, her seferinde biraz değişen aynı SQL ifadesini tekrar tekrar çalıştıran veritabanından kaynaklanmaktadır. Örneğin, bir veritabanı her defasında bir değişken için farklı bir değerle 10,000 kez bir SQL deyimi çalıştırabilir. Tüm bu durumlarda çözüm, bind değişkenlerini kullanmaktır.
 Her yürütmeden sonra tüm imleçleri açıkça kapatan bir uygulama da bu tür bir beklemeye katkıda bulunabilir.
 Bunun çözümü CURSOR_SPACE_FOR_TIME başlatma parametresini belirtmektir. Shared pool çok küçük olduğunda latch sorununa katkıda bulunabilir, bu nedenle SGA boyutunuzu kontrol edin.
  
   - Cache buffers LRU chain: Bu kilitlenme olayları genellikle aşırı buffer cache kullanımı nedeniyle oluşur ve gerek aşırı physical reads gerekse logical reads nedeniyle olabilir. Veritabanı "full table scans" gerçekleştiriyor veya "large index range scans" gerçekleştiriyor. Bu tür latch beklemelerinin olağan nedeni, bir index eksikliği veya unselective index varlığıdır. Ayrıca buffer cache boyutunu artırmanız gerekip gerekmediğini kontrol edin.
  
   - Cache buffer chains: Bu beklemeler, art arda erişilen bir veya daha fazla hot bloktan kaynaklanmaktadır.
   Sequence kullanmak yerine tablonun rowlarının sequence numaralarını oluşturmak için güncelleyen uygulama kodu , hot bloklara neden olabilir.
   Benzer işlemlerle çok sayıda işlem  unselective index tararken,  cache buffer chains wait event olayını da görebilirsiniz.
  
  - Ayrıca, sequences kullanıyorsanız bunları daha büyük bir cache boyutu ayarı ile yeniden oluşturun ve ORDER yan tümcesini kullanmaktan kaçınmaya çalışın. Bir sequence in CACHE değeri, veritabanının SGA'da önbelleğe alınması gereken sequence değerlerinin sayısını belirler. Veritabanınız çok sayıda insert ve update işliyorsa, sequence değerleri için contention u önlemek için cache boyutunu artırmayı düşünün. Varsayılan olarak, cache 20 değerlerine ayarlanır. Değerler, önbelleği sık sık tüketmek için hızlı bir şekilde istenirse, sonuç çıkabilir. Bir RAC ortamıyla uğraşıyorsanız, NOORDER yan tümcesini kullanmak sıraya alınan sıralı değerlerin zorla sıralanması nedeniyle enqueue contentionu önleyecektir.
 

  Nasıl Çalışır:
 
  - Oracle, çeşitli bellek yapılarını korumak için latches olarak adlandırılan iç kilitleri kullanıyor.
  Bir sunucu işlemi bir latch almaya çalışırken bunu yapmazsa, bu girişim latchsız bir bekleme olayı olarak sayılır.
  Oracle, tüm latch beklemelerini tek bir latchsız bekleme olayına gruplamıyor.
  Oracle genel bir latchsız bekleme olayı kullanıyor, ancak bu yalnızca küçük latch ile ilgili bekleme olayları içindir.
  En yaygın kullanılan latchlar için, Oracle bekleme olayı türünün adıyla çeşitli alt gruplardaki latch-related wait events olayları
  kullanır. latch event türüne bakarak tam latch türünü belirleyebilirsiniz. Örneğin, latch event latch: library cache, library cache latches için çakışmayı belirtir.
  Benzer şekilde, latch: cache buffer chains olayı arabellek önbellek için çakışmayı belirtir.
 
  - Oracle, birden fazla oturumun SGA'nın aynı alanını güncellemesini önlemek için çeşitli latch işlemleri kullanır.
  Çeşitli veritabanı işlemleri, SGA yı okumak veya güncellemek için sessionlar gerektirir. Örneğin, bir oturum bir veri bloğunu diskten SGA ya okurken, buffer cache de en son kullanılan kaydı değiştirmelidir. Benzer şekilde, veritabanı bir SQL deyimini pars ettiğinde, bu deyim SGA'nın library cache bileşenine eklenmelidir. Oracle, veritabanı işlemlerinin birbirine girmesini ve SGA'yı bozmasını önlemek için kilitleri kullanır.
 
  - Bir veritabanı işlemi, çok kısa sürelerle, genellikle birkaç nanosaniye süren bir latch alıp tutmalıdır.
 Latch zaten kullanımda olduğu için bir oturum bir latch kazanamazsa, oturum "sleep" durumuna geçmeden önce birkaç kez deneyecek. Oturum yeniden uyanacak ve ihtiyaç duyduğu mandalı hâlâ alamıyorsa, uyku moduna geçmeden önce birkaç kez daha deneyecek.
 Oturum uyku moduna girdiğinde her sefer daha uzun süre kalır, bu durum her latch edinme girişimi arasındaki zaman aralığını artırır.
  Dolayısıyla, veritabanızda latchler için ciddi bir contention varsa, yanıt sürelerinin ve çıktılarının ciddi bir şekilde düşmesine neden olur.
 
  - Çok hızlı bir donanımda çalışan iyi tasarlanmış bir veritabanında bile "latch contention" olduğunu görünce şaşırmayın.
  Bir miktar latch contention, "özellikle cache buffers chain latch events" olayları, kaçınılmazdır.
  Latch beklemeleri çok yüksekse ve veritabanı performansını yavaşlatıyorsa endişelenmelisiniz.
  - Shared pool latches ın yanı sıra library cache latches den kaynaklanan sorunlar, genellikle bind değişkenlerini kullanmayan uygulamalar nedeniyle oluşur.
  Uygulamanız bind değişkenlerini içerecek şekilde yeniden kodlanamazsa, hepsi kaybolmaz.
  CURSOR_SHARING parametresini, uygulamanız kodda belirtilmemiş olsa bile Oracle'ın bind değişkenlerini kullanmaya zorlaması için ayarlayabilirsiniz.
  Bu parametre için hard-coded değişken değerleri için bind değişkenlerinin yerini zorlamak için FORCE veya SIMILAR ayarı arasından seçim yapabilirsiniz. Bu parametrenin varsayılan ayarı EXACT'tır; bu, veritabanının literal değişkenleri için bind değişkenlerini değiştirmeyeceği anlamına gelir. CURSOR_SHARING parametresini FORCE olarak ayarladığınızda Oracle tüm değişkenleri bind değişkenlerine dönüştürür. SIMILAR , bind değişkenlerini yalnızca bir deyimin execution planını değiştirmediğinde kullanır. Böylece, SIMILAR ayarı, veritabanını literal yerine bind değişkenlerini kullanmaya zorlamak için daha güvenli bir yol gibi görünüyor.CURSOR_SHARING parametresini FORCE olarak ayarlama güvenliğiyle ilgili bazı endişelerimiz olmasına rağmen, bu ayarı kullanırken gerçek bir sorun görmedik.

CURSOR_SHARING parametresini FORCE veya SIMILAR olarak ayarladığınızda library cachete contention genellikle kaybolur.
 CURSOR_SHARING parametresi, latch contentionı ortadan kaldırarak hemen veritabanı performansını artıracak birkaç Oracle gümüş mermiden biridir. Library cache latch contention ile uğraşırken güvenle kullanın.
 
  -  Cache buffer chains latch contention, genellikle, aynı veri bloklarını art arda okuyan bir oturumdan kaynaklanmaktadır.
  Öncelikle, cache buffers chain latches in en yüksek miktarından sorumlu olan SQL deyimini belirleyin ve onu tune edip etmeyeceğinize karar verin. Bu, latch contentionı azaltmazsa, art arda okunmakta olan gerçek hot blokları tanımlamanız gerekir.
 
  - Hot bir blok bir index segmentine aitse, tabloyu partitioning yapmayı ve local indexleri kullanmayı düşünebilirsiniz.
  Örneğin, bir hash partitioning şeması, yükü multiple partitioned index arasında yaymanıza izin verir.
  Ayrıca, index eklenen sütunlara dayalı olarak tabloyu hash cluster based e dönüştürmeyi de düşünebilirsiniz.
  Böylece indexin tamamını önleyebilirsiniz. Hot bloklar bunun yerine bir tablo partition a aitse,
  bölmeyi dağıtmak için tabloyu bölümlemeyi düşünebilirsiniz. Aynı bloklara tekrar tekrar erişildiğini görmek için uygulama tasarımını yeniden gözden geçirmek ve böylece onları "hot" hale getirmek de isteyebilirsiniz.



Minimizing System Contention ( 19- Time Spent Waiting Due to Locking )

Time Spent Waiting Due to Locking
  
  
  - Kilitleme sorunları yüzünden oturumlar tarafından harcanan toplam süreyi belirlemek istiyorsunuz.
 
  - Bir tablonun satırlarının kilitlenmesinin neden olduğu beklemeleri tanımlamak (ve ölçmek) için aşağıdaki sorguyu kullanabilirsiniz.
  Sorgu, bekleme olaylarını bekleme zamanına göre sıraladığı için instance daki bekleme durumlarının çoğunu hangi bekleme olayları türleri oluşturduğunu hızla görebilirsiniz.
 
  SQL> select wait_class, event, time_waited / 100 time_secs
    from v$system_event e
    where e.wait_class <> 'Idle' AND time_waited > 0
    union
    select 'Time Model', stat_name NAME,
    round ((value / 1000000), 2) time_secs
    from v$sys_time_model
    where stat_name NOT IN ('background elapsed time', 'background cpu time')
    order by 3 desc;
   
    WAIT_CLASS  EVENT        TIME_SECS
   ------------ ---------------------------  -----------
   System I/O  log file parallel write   45066.32
   System I/O  control file sequential read  23254.41
   Time Model  DB time       11083.91
   Time Model  sql execute elapsed time   7660.04
   Concurrency  latch: shared pool     5928.73
   Application  enq: TX - row lock contention  3182.06
   …
   
  - Bu örnekte bekleme olayı  enq: TX - row lock contention, row lock enqueue wait events olaylarından dolayı toplam süreyi ortaya koymaktadır.
Shared pool latch events, Concurrency wait class ın altında sınıflandırılır , enqueue TX - row lock contention event olayı Application class wait event olarak sınıflandırılır.
 
 
  Nasıl Çalışır:
 
  - Yukarıdaki sorgu, çeşitli bekleme olaylarından dolayı beklenen toplam süreyi göstermek için V$SYSTEM_EVENT ve V$SYS_TIME_MODEL viewleri joinlenir. Bizim durumumuzda,"enqueue locking" nedeniyle beklenen toplam süreyle ilgileniyoruz.
Belirli bir oturumun beklediği toplam süreyle ilgileniyorsanız, oturumların bekleme durumunun ne kadar uzun olduğunu öğrenmek için birkaç farklı V$ view kullanabilirsiniz, ancak V$SESSION viewini kullanmanızı öneririz, çünkü blocking ve blocked oturumların çeşitli yararlı niteliklerini gösterir. Bir oturumun başka bir oturum tarafından ne kadar süreyle engellendiğini öğrenmenin bir yolu da aşağıdaki sorgu:
 
  SQL>select sid, username, event, blocking_session,
   seconds_in_wait, wait_time
   from v$session where state in ('WAITING');
  
   - Sorgu, bekleme durumundaki SID 81 olan session hakkında aşağıdakileri ortaya çıkarır:
  
   SID : 81 (this is the blocked session)
   username: SH (user who's being blocked right now)
   event: TX - row lock contention (shows the exact type of lock contention)
   blocking session: 68 (this is the "blocker")
   seconds_in_wait: 3692 (how long the blocked session is in this state)
  
   - Sorgu, SID 81 olan user SH'nin yaklaşık bir saat (3,692 saniye) engellendiğini ortaya koymaktadır.
Kullanıcı SH şu anda oturum 68 tarafından kilitlenmiş bir tabloda bir kilidi beklemede olarak gösterilir.
V$SESSION viewini, blocking ve blocked sessionları belirlemek için son derece yararlı olsa da,
kullanıcı oturumunda yer alan tablonun engellenmesine sebep olan SQL deyimini size söyleyemez.
Çoğu zaman, bir blocking durumuna dahil olan SQL deyimini tanımlamak, ifadenin kilitleme davranışına tam olarak neden olduğunu bulmakta yardımcı olur. Gerçek SQL deyimini öğrenmek için, burada gösterildiği gibi V$SESSION ve V$SQL viewlerinin joinlenmesi gerekir.
  
  
   SQL> select sid, sql_text
    from v$session s, v$sql q
    where sid in (68,81)
    and (
    q.sql_id = s.sql_id or q.sql_id = s.prev_sql_id)
    SID    SQL_TEXT
   -------------  -----------------------------------------------------
    68    select * from test for update
    81    update hr.test set name='nalapati' where user_id=1111

  -Sorgunun çıktısı, SELECT 68 ... FOR UPDATE deyimini kullanarak oturum 68 tarafından kilitlenmiş bir tablodaki bir satırı güncelleştirmeye çalıştığı için oturum 81 engellendiğini gösterir. Bu gibi durumlarda, başka bir oturum tarafından engellenen kullanıcı oturumlarının uzun bir sırasını bulursanız, diğer oturumların çalışmalarını işleyebilmesi için blocking sessionu sonlandırmanız gerekir. Bu durumlarda veritabanında yüksek active session sayısı da görürsünüz.
Blocking sessionun kesilmesi, "enqueue locks" un neden olduğu çekişmeyi çözmek için size derhal bir çözüm sunar.
   Daha sonra, bu durumları önlemek için blockların neden oluştuğunu araştırabilirsiniz.
  
  - Herhangi bir oturum için, aşağıdaki sorguyu vererek, her wait class için bir oturum tarafından beklenen toplam süreyi belirleyebilirsiniz:
 
  SQL> select wait_class_id, wait_class,
   total_waits, time_waited
   from v$session_wait_class
   where sid = <SID>;
  
  - Örneğin, bu oturumun, application wait classda (bu sınıf için wait class ID 4217450380 ) çok fazla sayıda bekleme yaptığını bulursanız, V$SYSTEM_EVENT viewini kullanarak aşağıdaki sorguyu verebilirsiniz;
 
  SQL> select event, total_waits, time_waited
    from v$system_event e, v$event_name n
    where n.event_id = e.event_id
    and e.wait_class_id = 4217450380;
  
   EVENT      TOTAL_WAITS    TIME_WAITED
   --------------------  ------------   ------------
   enq: TM - contention   82       475
   
  - Örneğimizde, application classdaki (ID 4217450380) beklemeler, bekleme olayı enq:TM - contention dan kaynaklanmaktadır.
V$EVENT_HISTOGRAM viewini, instance ı başlattığınızdan beri belirli bir bekleme olayı için oturumların kaç kez beklediğini öğrenmek için de kullanabilirsiniz.
Kapatılan enqueue lock waits de bekleme süresi modelini bulmak için aşağıdaki sorguyu kullanabilirsiniz:
 
  SQL> select wait_time_milli bucket, wait_count
    from v$event_histogram
    where event = 'enq: TX - row lock contention';
 
  - Kilitleme davranışından ötürü yüksek miktarda "enqueue waits" genellikle hatalı uygulama tasarımından kaynaklanmaktadır.
 
  - Bu dört DML locking contention a neden olabilir: INSERT, UPDATE, DELETE ve SELECT FOR UPDATE. INSERT deyimleri bir kilit beklemektedir, çünkü başka bir oturum aynı değeri olan bir satır eklemeye çalışıyor. Bu, genellikle, key üreten uygulamanın  primary keyi veya unique constrainti olan bir tablonuz olduğunda ortaya çıkar. Bu tür kilitleme durumlarından kaçınmak için key değerlerini oluşturmak için onun yerine bir Oracle sequence kullanın. Kilitler nedeniyle oturum engellemeyi ortadan kaldırmak için NOWAIT seçeneğini bir SELECT FOR UPDATE deyimi ile belirtebilirsiniz.
Sessionlar bir UPDATE veya DELETE deyimi verdiklerinde, oturumlar tarafından kilitler için beklemekten kaçınmak için SELECT FOR UPDATE NOWAIT deyimini de kullanabilirsiniz. SELECT FOR UPDATE NOWAIT deyimi satırı beklemeden kilitler.







Minimizing System Contention ( 18- Recent Wait Events )


18- Recent Wait Events

- En yaygın bekleme olayları ve SQL ifadeleri, veritabanı nesneleri ve bu beklemelerden sorumlu olan kullanıcılar hakkında bilgi almak için V$ACTIVE_SESSION_HISTORY viewini sorgulayın. Aşağıda, kullanabileceğiniz bazı yararlı sorguları bulabilirsiniz.

 Son 15 dakika içinde oluşan en önemli bekleme olaylarını bulmak için aşağıdaki sorguyu çalıştırın:

    SQL> select event,
     sum(wait_time +
     time_waited) total_wait_time
     from v$active_session_history
     where sample_time between
     sysdate - 30/2880 and sysdate
     group by event
     order by total_wait_time desc;




 Kullanıcılarınızdan hangisinin son 15 dakika içinde en çok beklediğini öğrenmek için aşağıdaki sorguyu çalıştırın:

    SQL> select s.sid, s.username,
     sum(a.wait_time +
     a.time_waited) total_wait_time
     from v$active_session_history a,
     v$session s
     where a.sample_time between sysdate - 30/2880 and sysdate
     and a.session_id=s.sid
     group by s.sid, s.username
     order by total_wait_time desc;
 

En yüksek beklemeleri olan nesneleri bulmak için aşağıdaki sorguyu çalıştırın:

    SQL>select a.current_obj#, d.object_name, d.object_type, a.event,
     sum(a.wait_time +
     a.time_waited) total_wait_time
     from v$active_session_history a,
     dba_objects d
     where a.sample_time between sysdate - 30/2880 and sysdate
     and a.current_obj# = d.object_id
     group by a.current_obj#, d.object_name, d.object_type, a.event
     order by total_wait_time desc;
    
   Aşağıdaki sorgu ile son 15 dakika içinde en çok bekleyen SQL deyimlerini belirleyebilirsiniz:

    SQL> select a.user_id,u.username,s.sql_text,
     sum(a.wait_time + a.time_waited) total_wait_time
     from v$active_session_history a,
     v$sqlarea s,
     dba_users u
     where a.sample_time between sysdate – 30/2880 and sysdate
     and a.sql_id = s.sql_id
     and a.user_id = u.user_id
     group by a.user_id,s.sql_text, u.username;
    
  Nasıl Çalışır:

  - Yukarıdaki bölüm,son birkaç dakika içinde en çok bekleme olayına neden olan veya kimin beklediğini tam olarak öğrenmek için V$ACTIVE_SESSION_HISTORY viewine V$SESSION, V$SQLAREA, DBA_USERS ve DBA_OBJECTS gibi diğer viewlerle nasıl joinleneceğini gösterir.

Bu bilgiler "canlı" veritabanı performansı sorunlarını gidermek için son derece yararlıdır.

Minimizing System Contention ( 17- Son Locked Session ları Belirleme )

Son Locked Session ları Belirleme

  - Bir session, büyük olasılıkla başka bir oturum tarafından yerleştirilen blocking lock dan dolayı veritabanında ciddi bekleyişler yaşıyor.
V$LOCK'ı ve diğer viewleri kilitleme konusunu daha derinlemesine incelemek için kullanmaya çalıştınız, ancak kilit meydana gelirken "yakalayamıyorsunuz". Kilitleme devam ederken kaçırmış olabileceğiniz daha eski kilitleme verilerini "görmek" için farklı bir view kullanmak istiyorsunuz.

  - Önceki beş dakika boyunca(zaman aralığını değiştirebilirsiniz) veritabanında tutulan tüm kilitler hakkında bilgi bulmak için ASH'ye dayalı aşağıdaki ifadeyi uygulayabilirsiniz.
 
   SQL> select to_char(h.sample_time, 'HH24:MI:SS') TIME,h.session_id,
    decode(h.session_state, 'WAITING' ,h.event, h.session_state) STATE,
    h.sql_id,
    h.blocking_session BLOCKER
    from v$active_session_history h, dba_users u
    where u.user_id = h.user_id
    and h.sample_time > SYSTIMESTAMP-(5/1440);
 
   TIME  SID  STATE         SQL_ID    BLOCKER
   --------- ---  --------------------------------- -------------- --------
   17:00:52  197  116 enq: TX - row lock contention  094w6n53tnywr  191
   17:00:51  197  116 enq: TX - row lock contention  094w6n53tnywr  191
   17:00:50  197  116 enq: TX - row lock contention  094w6n53tnywr  191

  - ASH, oturum 1, oturum 2, blocked session  (SID = 197) için "bekletme" durumuna neden olan blocking session (SID = 191) yaptığı tüm blokları kaydettiğini görebilirsiniz.

  Nasıl Çalışır:

  - Genellikle, veritabanı kullanıcılarınız bir performans sorunu hakkında şikayet ettiğinde, V$SESSION veya V$LOCK viewlerini sorgulayabilir, ancak orada yararlı bir şey bulamayabilirsiniz, çünkü bekleme sorunu o zamana kadar çözülmüş olabilir.
  Bu koşullar altında, V$ACTIVE_SESSION_HISTORY görünümünü, önceki 60 dakika boyunca veritabanında neyin meydana geldiğini bulmak için sorgulayabilirsiniz. Bu view, Active Session History (ASH) bir pencere sunar; bu, her active session hakkında saniyede bir bilgi toplayan bir hafıza arabelleğidir. V$ACTIVE_SESSION_HISTORY, her active session için bir satır içerir ve ASH dönen bir arabellek olduğundan, yeni bilgiler sürekli olarak eski verilerin üzerine yazılır.

  - Aşağıda bir örnek senaryo mevcut

  SQL> create table test (name varchar(20), id number (4));
  Table created.
  SQL>
 
  SQL> insert into test values ('alapati','9999');
  1 row created.
  SQL> insert into test values ('sam', '1111');
  1 row created.
  SQL> commit;
  Commit complete.

  - Session 1'de (geçerli oturum), TEST tablosundaki SELECT * FOR UPDATE deyimini yürütün; bu tabloya bir lock yerleştirecektir.

  SQL> select * from test for update;

  - Session 2, farklı bir oturumda aşağıdaki UPDATE deyimini çalıştırın:

  SQL> update test set name='Jackson' where id = '9999';

  - Session 2, Session 1 tarafından yayınlanan SELECT FOR UPDATE deyimi tarafından engellendiğinden, şimdi askıda kalacaktır.
  Şimdi devam edin ve Session 1'den bir ROLLBACK veya bir COMMIT işlemi yapın:

  SQL> rollback;
  Rollback complete.

  - ROLLBACK deyimini verdiğinizde, Session 1 şu anda TEST'de tuttuğu tüm kilitleri serbest bırakır. Şimdiye kadar engellenmiş olan Session 2'nin daha önce "hanging" olan UPDATE bildirimini hemen işlediğini fark edeceksiniz.

  - Bu nedenle, veritabanınızda Session 1 ve Session 2 blocked session ile kısa bir süre için bir blocking lock olur. Bununla birlikte, V$LOCK viewında bununla ilgili herhangi bir kanıt bulamazsınız, çünkü bu ve diğer tüm kilitle ilişkili viewler, yalnızca o anki kilitlerle ilgili ayrıntıları gösterir. Active Session History viewlerinin bu noktada öne geçtiği yer: yakınlarda düzenlenen ancak bunları V$LOCK veya V$SESSION viewlerinde bir sorgu ile görüntülemeden önce zaten kaybolmuş olan kilitler hakkında bilgi sağlayabilirler.

  Not: Yukarıdaki bölümde gösterilen Active Session History (ASH) sorgusunu yürütülürken dikkatli olun.
  İlk sütun (SAMPLE_TIME) gösterildiği gibi, ASH her saniye oturum bilgisini kaydeder. Bu sorguyu uzun bir zaman aralığında yürütürseniz, aynı kilitleme bilgilerini tekrar ederek çok fazla miktarda çıktı alabilirsiniz.
  Bu çıktıyı incelemek için, SQL * Plus'da SET PAUSE ON seçeneğini belirtebilirsiniz.
  Bu, her sayfanın çıktısını duraklatarak, sorunu tanımlamak için çıkışın birkaç satırını kaydırmanıza olanak tanır.


  - Bu oturumun son bir saat boyunca beklediği wait eventsi bulmak için aşağıdaki sorguyu kullanın.


  SQL> select sample_time, event, wait_time
   from v$active_session_history
   where session_id = 81
   and session_serial# = 422;

  - SAMPLE_TIME sütunu, belirli bir wait event dan dolayı bu oturumun ne zaman performans sorunu gösterdiğini tam olarak bilmenizi sağlar.
  Burada gösterildiği gibi, V$SQL viewı V$ACTIVE_SESSION_HISTORY viewile birlikte kullanarak, bu oturum tarafından yürütülen gerçek SQL deyimini tanımlayabilirsiniz:

  SQL> select sql_text, application_wait_time
   from v$sql
   where sql_id in ( select sql_id from v$active_session_history
   where sample_time = '08-MAR-11 05.00.52.00 PM'
   and session_id = 68 and session_serial# = 422);


  - Alternatif olarak, V$ACTIVE_SESSION_HISTORY viewında zaten SQL_ID'ye sahipseniz, burada gösterildiği gibi SQL_TEXT sütunundaki değeri V$SQLAREA viewiden elde edebilirsiniz:

  SQL> select sql_text FROM v$sqlarea WHERE sql_id = '7zfmhtu327zm0';

  - SQL_ID öğesine sahip olduğunuzda, bu SQL deyimi için DBMS_XPLAN paketine dayalı aşağıdaki sorguyu çalıştırarak SQL Planı çıkarmak da kolaydır:

  SQL> select * FROM table(dbms_xplan.display_awr('7zfmhtu327zm0'));

  - MMON, AWR snapshot oluşturulduğunda, ASH verilerini her saat diske akıtıyor. MMON ASH verilerini diske attığında ne olur?
 Artık, eski verileri artık V$ACTIVE_SESSION_HISTORY viewile sorgulayamayacaksınız. Merak etmeyin, çünkü eski verileri sorgulamak için DBA_HIST_ACTIVE_SESS_HISTORY viewını kullanmaya devam edebilirsiniz. Bu viewın yapısı V$ACTIVE_SESSION_HISTORY viewının yapısına benzer. DBA_HIST_ACTIVE_SESS_HISTORY viewı, son sistem etkinliğinin in-memory active session history içeriğinin geçmişini gösterir. Hala etkin durumdayken bir oturumun son on bekleme olayını incelemek için V$SESSION_WAIT_HISTORY viewinden sorgulayabilirsiniz. Bu view, son bekleme olayları için her ikisi de yalnızca en yeni bekleme durumunun bekleme bilgilerini gösteren V$SESSION ve V$SESSION_WAIT viewlerinden daha güvenilir bilgiler sunar.
  İşte V$SESSION_WAIT_HISTORY viewini kullanan tipik bir sorgu.
 
  SQL> select sid from v$session_wait_history
  where wait_time = (select max(wait_time) from v$session_wait_history);

  - WAIT_TIME sütununda sıfır olmayan herhangi bir değer, bu oturumun beklediği zamanı temsil eder.
 Son bekleme olayı. Bu sütunun sıfır değeri oturumun bir bekleme olayı için beklediği anlamına gelir.

Minimizing System Contention ( 16- enq: TM Lock Contention )

Enq: TM Lock Contention
 
  - Veritabanınızdaki birkaç oturum, bazı insert ifadelerini işlemek için çok uzun zaman alıyor.
Sonuç olarak, "active" session sayısı çok yüksek ve veritabanı yeni oturum bağlantılarını kabul edemiyor. Kontrol ettiğimizde, veritabanının bir çok "enq: TM - contention wait" olayı yaşadığını fark ettiniz.
 
  - Insert işlemlerini gerçekleştirmek için bekleyen oturumların "enq: TM – contention event" olayındaki beklemeler, genelde indexsiz foreign key kısıtlamasından kaynaklanmaktadır.
Bu, bir parent tabloya bağımlı veya child tablonun foreign key kısıtlamasında ilişkili keylerde bir index eksik olduğunda ortaya çıkar.
Oracle, child tablodaki foreign key tarafından başvurulan parent tablodaki PK sütununda değişiklikler yapıyorsa, child tablo üzerinde bir tablo kilidi alır.
Bunların tam tablo kilitleri (TM) olduğunu ve satır düzeyi kilitleri (TX) olmadığını unutmayın; bu kilitler bir satırla sınırlı değil, tablonun tamamında görülür.
Doğal olarak, bu tablo kilidi elde edildiğinde Oracle, child tablonun verilerini değiştirmeye çalışan tüm diğer oturumları engeller. Üst tablonun sütununa başvuran child tabloya bir index oluşturduktan sonra, "TM contention" nedeniyle bekleyişler kaybolacaktır.
 
 
  Nasıl Çalışır:
  - Tablodaki foreign key kısıtlamalarını indexlemezsiniz, child tabloda exclusive lock alır.
Indeksllenmemiş foreign key kilitleme nedeniyle contention ile sonuçlanacağını göstermek için aşağıdaki örneği kullanın. Burada gösterildiği gibi iki table (STORES ve PRODUCTS) oluşturun:
  
   SQL> create table stores
    (store_id number(10) not null,
    supplier_name varchar2(40) not null,
    constraint stores_pk PRIMARY KEY (store_id));
   SQL>create table products
    (product_id number(10) not null,
    product_name varchar2(30) not null,
    supplier_id number(10) not null,
    store_id number(10) not null,
    constraint fk_stores
    foreign key (store_id)
    references stores(store_id)
    on delete cascade);
   
  - STORES tablosundaki herhangi bir satırı silerseniz, kilitleme nedeniyle beklemeleri farkedeceksiniz. PRODUCTS tablosunda foreign key olarak belirttiğiniz sütunda yalnızca bir index oluşturarak bu beklemelerden kurtulabilirsiniz:
 
 create index fk_stores on products(store_id);
 
  - Aşağıdaki sorgu ile veritabanınızda indexli tüm foreign key kısıtlamalarını bulabilirsiniz:
 
   SQL> select * from (
     select c.table_name, co.column_name, co.position column_position
     from user_constraints c, user_cons_columns co
     where c.constraint_name = co.constraint_name
     and c.constraint_type = 'R'
     minus
     select ui.table_name, uic.column_name, uic.column_position
     from user_indexes ui, user_ind_columns uic
     where ui.index_name = uic.index_name
     )
     order by table_name, column_position;
    
  - Bir foreign key sütununa index eklemezseniz, child table sıklıkla kilitlenir, dolayısıyla contention ile ilgili beklemelere neden olur. Oracle, foreign keylere daima index eklemenizi önerir.
 
 Tip: Alt tablodaki foreign keye bağlı unique veya primary key asla güncelleştirilmez veya silinmezse , alt tablodaki foreign key sütununu indexlemek zorunda değilsiniz
 
 
  - Oracle, foreign key sütununu index eklemezseniz child tabloda bir tablo kilit elde etme eğiliminde olacaktır.
Parent tabloya bir satır eklerseniz, parent tablo child tabloda bir kilit elde etmez; Ancak, parent tabloda bir satır güncelleştirir veya silerseniz, child tabloda kilit meydana gelecektir. Diğer bir deyişle, üst tablodaki primary keydeki herhangi bir değişiklik, alt tabloda full table lock (TM) ile sonuçlanır. Örneğimizde STORES tablosu, STORE_ID foreign key içeren PRODUCTS tablosunun üst öğesidir. Değişken bir tablo olan PRODUCTS tablosundaki STORE_ID sütununun değerleri,
üst tablo olan STORES tablosunun unique veya primary key değerleriyle eşleşmelidir.
Bu durumda, STORES tablosundaki STORE_ID sütunu, o tablonun primary keyidir.

- Üst tablonun (STORES) primary keyini değiştirdiğinizde, veritabanı, PRODUCTS tablosunda full table lock alır.
Diğer oturumlar, foreign key sütunundan başka sütunlar da dahil olmak üzere, PRODUCTS tablosunda herhangi bir değeri değiştiremez. Oturumlar yalnızca PRODUCTS tablosunu sorgulayabilir ancak değiştiremez.
Bu süre zarfında, PRODUCTS tablosundaki herhangi bir sütunu değiştirmeye çalışan herhangi bir oturumun beklemesi gerekecek (TM: enq contention wait). Oracle, alt tablodaki (PRODUCTS) kilidi yalnızca ana tablodaki (STORES) primary keyi değiştirmeyi tamamladıktan sonra serbest bırakacaktır.
PRODUCTS tablosundaki verileri değiştirmek için bekleyen bir sürü oturumunuz varsa, hepsi beklemek zorunda kalacaklar ve kısa DML işlemlerini gerçekleştiren birçok kullanıcısı olan bir online transaction processing türü veritabanına sahipseniz, active session sayısı doğal olarak çok hızlı yükselir.
Alt tabloda gerçekleştirdiğiniz tüm DML işlemlerinin, üst tabloda bir tablo kilidi gerektirmediğini unutmayın.

Minimizing System Contention ( 15- Locked Object yi Bulma )

15- Locked Object Bulma
  - Locked object kimliğini, V$LOCK görünümünde ID1 (LockIdentifier) sütununun değerine bakarak bulabilirsiniz (bkz. Konu 13).
  TYPE sütununun TM (DML enqueue) olduğu ID1 sütununun değeri, kilitli nesneyi tanımlar. Diyelim ki ID1 sütununun değeri 99999'dur.
  Daha sonra kilitli tabloyu tanımlamak için aşağıdaki sorguyu çalışabilirsiniz:
 
   SQL> select object_name from dba_objects where object_id=99999;
    OBJECT_NAME
    ------------
    TEST
 
  - Daha da kolay bir yol, kilitli nesneyi, nesne türünü ve nesnenin sahibini bulmak için V$LOCKED_OBJECT viewını kullanmaktır.
 
   SQL> select lpad(' ',decode(l.xidusn,0,3,0)) || l.oracle_username "User",
     o.owner, o.object_name, o.object_type
     from v$locked_object l, dba_objects o
     where l.object_id = o.object_id
     order by o.object_id, 1 desc;
     
    User  OWNER  OBJECT_NAME  OBJECT_TYPE
    ------  ------  ------------ ------------
    HR   HR   TEST    TABLE
    SH   HR   TEST    TABLE

  - Yukarıdaki sorgunun hem blocking session ı hemde blocked sessionı gösterdiğini unutmayın.
  
  
  Nasıl Çalışır:
 
  - Yukarıdaki bölümünde gösterildiği gibi kilitli bir nesneyi tanımlamak oldukça kolaydır. Kilitli bir nesneyi, kilitte yer alan nesnenin ROWID'ini ve kilitlerden sorumlu olan SQL deyimini hızlı bir şekilde tanımlamak için Oracle Enterprise Manager'ı kesinlikle kullanabilirsiniz. Bununla birlikte, kilitleme bilgisini içeren temel Oracle viewlarını anlamak her zaman önemlidir . Bu konuda gösterilen sorguları kullanarak, Oracle Enterprise Manager gibi bir izleme aracını kullanmadan kilitli bir nesneyi kolaylıkla tanımlayabilirsiniz.
  - Yukarıda gösterilen örnekte, kilitli nesne bir tabloydu, ancak bir PL/SQL paketi de dahil olmak üzere başka herhangi bir obje türü de olabilir. Genellikle, bir sorgunun hang kalmasının sebebi, sorgunun gerektirdiği nesnelerden birinin kilitli olmasıdır. Diğer kullanıcıların nesneye erişebilmesi için nesnedeki kilidi tutan oturumu kapatmanız gerekebilir.
 
 

Minimizing System Contention ( 14- Blocking Lock ile Başetme )


Blocking Lock ile Başetme


  - Bir blocking lock ile uğraşırken iki temel strateji vardır: kısa vadeli ve uzun vadeli bir strateji.
 Yapmanız gereken ilk şey, "blocking lock" ı ortadan kaldırmak, böylece oturumlar kuyrukta kalmaya devam etmeyecektir
 - Düzinelerce hatta yüzlerce oturumdan tek bir  blocking lockın olması hiç de nadir değildir, hepsi bloklanan objeyi beklemektedir.
 Blocking session SID'sini zaten bildiğinizden (örneğimizde oturumumuz 68), oturum için ilgili serial# için V$SESSION viewını sorguladıktan sonra oturumu bu şekilde sonlandırın:

  SQL> alter system kill session '68, 1234';
 
  - Kısa vadeli çözüm, "blocking locks" tan hızlı bir şekilde kurtulmak ve böylece veritabanınızın performansına zarar vermemektir. Blocking session ı basitçe kill ederek onlardan kurtulursun. Blocking session ın arkasında bekleyen blocked session ların uzunca sıralandığını görürseniz, diğer oturumların devam edebilmesi için blocking sessionı kill edin.
 
  - Uzun vadede, blocking session ın neden bu şekilde davrandığını araştırmanız gerekir. Genellikle, uygulama mantığında bir kusur bulacaksınız. Bununla birlikte, blocking sessionın yürüttüğü SQL kodunun derinliklerine inmeniz gerekebilir.
 
 
  Nasıl Çalışır:

  - Bu örnekte açıkçası, "blocking lock" bir DML kilidi. Bununla birlikte, bunu bilmiyorisek , V$LOCK viewının TYPE (TY) sütununu inceleyerek kilidin türünü bulabilirsin. Oracle, library cache i ve diğer bileşenleri korumak için çeşitli iç "sistem kilidi" türlerini kullanmaktadır ancak bu kilitler normaldir ve V$LOCK görünümünde bu kilitlerle ilgili bir şey bulamazsınız.
 
  - DML işlemleri için Oracle, iki temel kilit türü kullanır: transaction locks (TX) ve DML locks (TM).
  Üçüncü tip bir kilit, user lock (UL) var, ancak genel kilitleme sorunlarının giderilmesinde rol oynamıyor.
  Transaction locks, Oracle kilitleme sorunlarını gidermek için karşılaşacağınız kilitlerin en sık kullanılan türdür.
  Bir transaction, veri her değiştirdiğinde, row transaction lock olan TX kilidini çağırır. Öte yandan, DML kilidi TM, bir DML ifadesi tarafından değiştirilen her nesne için bir kez edinilir.
 
  - LMODE sütunu, "6" numaralı özel bir kilidi belirterek, kilit modunu gösterir. REQUEST sütununda istenen kilit modu gösterilir. Bir satırı ilk değiştiren oturum, LMODE = 6 ile özel bir kilit tutar.
  Bu oturumun REQUEST sütununda, bir kilit istemediğinden 0 değeri gösterilir; zaten bir kilidi vardır!
  Blocked session ın ihtiyacı olmasına rağmen aynı satırlarda özel bir kilit elde edemiyor, bu nedenle de özel modda (MODE = 6) bir TX isteğinde bulunuyor. Yani, engellenen oturumun REQUEST sütununda 6, LMODE sütununda 0 değerinde (engellenen bir oturum hiç bir modda kilitlenmez) bir değer gösterecektir.
 
  - Önceki tartışma, her zaman özel modda alınan "row locks" için geçerlidir.
  Bir TM kilidi normalde "Shared Row Exclusive mode" olan mod 3'te kazanılırken, bir DDL bildirimi bir TM özel kilidine ihtiyaç duyar.
 

Minimizing System Contention ( 13- Blocked ve Blocking Sessions'ları Belirleme )

Blocked ve Blocking Sessions'ları Belirleme


  - Oracle veritabanında bir "enqueue wait event"ı gördüğünüzde, bazı oturumların SQL deyimlerini yürütmesini bekleyen locking ihtimali vardır. Bir oturum "enqueue" wait olayında beklerse, bu oturum farklı bir oturum tarafından tutulan locktan dolayı beklemektedir. Engellenen ve engelleyen oturumlarla ilgili bilgileri görüntülemek için aşağıdaki komutu kullanabilirsiniz:
 
 
   SQL> select decode(request,0,'Holder: ','Waiter: ')||sid sess,
     id1, id2, lmode, request, type
     from v$lock
     where (id1, id2, type) in
     (select id1, id2, type from v$lock where request>0)
     order by id1, request;
 
  - V$LOCK viewı, instance da herhangi bir blocking lock olup olmadığını gösterir. Blocking lock varsa, engelleyen oturumları ve engellenen oturumları da gösterir. Blocking sessionın, hepsinin bloke edildiği nesneye ihtiyacı olursa, aynı anda birden fazla oturumu engelleyebileceğini unutmayın.
  Kilitleri gösteren bir örnek:
 
    SQL> select sid,type,lmode,request,ctime,block from v$lock;
     SID TY  LMODE REQUEST  CTIME  BLOCK
    ----- ---- ------ -------- ------  ------
     127  MR    4   0   102870   0
     81  TX    0   6   778    0
     191  AE    4   0   758    0
     205  AE    4   0   579    0
     140  AE    4   0   11655    0
     68  TM    3   0   826    0
     68  TX    6   0   826    1
   
  - İlk bakmamız gereken sütun BLOCK sütunudur - blocking session bu sütun için 1 değerine sahip olacaktır.
  Örneğimizde, oturum 68 blocking sessiondır, çünkü BLOCK sütununun altında 1 değeri gösterilmektedir.
  Böylece, V$LOCK viewı bu tarife yukarıdaki bölümündeki ilk bulguyu teyit eder. SID si 68 olan blocking sessionı  ayrıca LMODE sütununda, bu kilidi exclusive mode tuttuğunu gösteren bir lock modu "6" gösterir - 81 oturumu "hanging",  güncelleme işlemini gerçekleştirememektedir. Elbette blocked session kurbanı olduğu için BLOCK sütununda 0 değeri  gösterilir. Ayrıca, sütun güncelleme gerçekleştirmek için exclusive mode da bir kilitleme isteği nedeniyle, REQUEST sütununun altında 6 değeri gösterilmektedir. Blocking session REQUEST sütununda 0 değerini göreceksiniz çünkü herhangi bir kilit istemiyor - zaten tutuyor:)
 
  - Wait class ı öğrenmek ve bir blocking session ın diğerlerini ne kadar engellediğini öğrenmek isterseniz, burada gösterildiği gibi V$SESSION viewını sorgulayarak bulabilirsiniz:
 
  SQL> select blocking_session, sid, wait_class,
    seconds_in_wait
    from v$session
    where blocking_session is not NULL
    order by blocking_session;
  
   BLOCKING_SESSION SID  WAIT_CLASS  SECONDS_IN_WAIT
   ----------------- -------- ------------- ----------------
    68     81  Application   7069
 
 
   SID si 68 olan oturum , SID si 81 olan oturumu engellediğini ve bloğun 7069 saniye önce başlatıldığını gösterir.
  
  Nasıl Çalışır:
 
  - Bir Oracle veritabanında göreceğiniz "enqueue lock" ların en yaygın türleri şunlardır:
 
   TX: Bunlar bir  transaction locktır ve genellikle hatalı uygulama mantığından kaynaklanır.
  • TM: Bunlar tablo düzeyi DML kilitlemeleridir ve en yaygın nedeni, child tabloda foreign keyleri indexlememenizdir.
 
  - Buna ek olarak, duruma göre "ST enqueue lock" larıda görme ihtimaliniz var. Bu, Oracle'ın disk yönetimi işlemleri yaparken beklediği oturumları belirtir; örneğin, bir sort işlemi gerçekleştirmek için temporary segment tahsisi.

 

Minimizing System Contention ( 12- Blocking Lock Olayını Tesbit Etme )


12- Blocking Lock Olayını Tesbit Etme

  - Kullanıcılarınız oturumlarının bazılarının çok yavaş olduğundan şikayet ediyor.
  Bu oturumların Oracle tarafından locklanmış olabileceğinden şüpheleniyorsunuz ve bu oturumları kimin elinde tuttuğunu bulmak istiyoruz.
  
  - Oracle, veritabanında yıkıcı davranışları önlemek için, birden çok oturum tarafından yürütülen işlemleri kontrol etmek için çeşitli lock türleri kullanmaktadır.
  Bir blocking lock, bir oturumu "yavaşlatabilir" ,aslında oturum yalnızca bir nesne üzerinde lock (tek satır veya bir dizi satır veya bir tablonun tamamında) tutan başka bir oturumu bekliyor demektir.
  Veya bir development senaryosunda, bir developer birden çok oturum başlatmış olabilir ve bazıları birbirini engelliyor.

  - Oracle locklarını analiz ederken incelemeniz gereken lock veritabanı viewlarının bazıları V$LOCK ve V$SESSION dir.
  Locklı objeleri tanımlamak için V$LOCKED_OBJECT ve DBA_OBJECTS viewleri de çok yararlıdır. Bir oturumun başka bir oturuma uyguladığı tler tarafından engellenip engellenmediğini öğrenmek için aşağıdaki sorguyu uygulayabilirsiniz:

  - Bir oturumun başka bir oturum ile "lock" ile engellenip engellenmediğini bulmak için aşağıdaki sorguyu çalıştırın :

  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
  --------------------------------------------------------------------
  
HR@MIRO\MIROPC61 ( SID=68 ) is blocking SH@MIRO\MIROPC61 ( SID=81 )

  - Sorgunun çıktısı blocking session yanı sıra tüm blocked sessions larıda gösterir.

  - Herhangi bir user için instance da herhangi bir  "blocking locks" olup olmadığını öğrenmenin hızlı bir yolu :
 
   SQL> select * from V$lock where block > 0;
 
  - Bu sorguda herhangi bir satır almazsanız, şu anda instance da herhangi bir "blocking locks" yok!

  Nasıl Çalışır:

  - Oracle yıkıcı davranışı(destructive behavior) önlemek için iki tür kilit kullanır: exclusive ve shared locklar.
  Aynı obje üzerinde birden çok shared lock elde edilebilinirken yalnızca bir transaction bir satır veya tablo üzerinde exclusive lock elde edilebilir.
  Oracle kilitleri, row ve tablo düzeyleri olmak üzere iki düzeyde kullanır. TX simgesi ile gösterilen row kilitleri, yalnızca INSERT, UPDATE ve DELETE gibi bir DML ifadesi tarafından değiştirilecek her satıra ait bir tablo satırı kilitler.
  Bu, aynı zamanda bir merge veya bir SELECT ... FOR UPDATE deyimi için de geçerlidir. Bu ifadelerden birini içeren işlem, exclusive lock kilidinin yanı sıra row share table kilidini de kapar.
  Transaction (ve oturum), bu kilitleri commit edilene veya roll back yapana kadar tutar.
  Bu iki şeyden birini yapana kadar, belirli bir satırı değiştirmeyi düşünen diğer tüm oturumlar blocklanır.
  Bir transaction un tablonun satırlarını veya satırlarını değiştirmeyi planladığı seferde,
  o tablonun üzerinde tablo lock (TM) tutar ve bu tablonun herhangi bir DDL işlemine (örneğin DROP TABLE) izin vermez.
 
  Oracle database de, "locking" şu şekilde çalışır:
  • Bir okuyucu, başka bir okuyucuyu engellemeyecektir.
  • Bir okuyucu bir yazıcıyı engellemeyecektir.
  • Bir yazıcı, aynı veriler üzerindeki okuyucuyu engellemeyecektir.
  • Bir yazıcı, aynı veriyi değiştirmek isteyen başka bir yazıcıyı engelleyecektir.

- Yukarıdaki listede son durum, iki session bir tabloda aynı verileri değiştirmeyi planladığında
Oracle'ın otomatik kilitlemesini yıkıcı davranışı(destructive behavior) önlemek için başlatır.
Varolan bir satırı update edecek ilk transaction, o satırda exclusive lock alır.
Bir satırı kilitleyen ilk oturum, (COMMIT veya ROLLBACK işlemi yapana kadar) bu kilidi tutmaya devam ederken, diğer oturumlar bu tablodaki kilitlenmiş satır dışındaki diğer satırları değiştirebilir.
Birinci oturumda tutulan table lock, yalnızca diğer oturumların tablo yapısını değiştirmek için bir DDL ifadesi yayınlamasını önlemeyi amaçlamaktadır.
Oracle, karmaşık bir kilitleme mekanizması kullanır; bu sayede, row-level lock otomatik olarak tabloya veya blok seviyesine yükseltilmez,row bazında kalır.

Minimizing System Contention ( 11- Recovery Writer Waits )

Recovery Writer Waits

  - Veritabanınızdaki Oracle Flashback Database özelliğini açtınız. Şu anda yavaş bir RVWR (recovery writer) işlemi nedeniyle çok sayıda bekleme olayı görüyorsunuz. Recovery writer ın bekleyişlerini azaltmak istiyorsunuz.
 
  - Oracle değişen tüm blokları memoryden diskteki flashback loglarına yazar.Database flashback loglarına yazarken top event de "flashback buf free by RVWR wait event"  olayı ile karşılaşabilirsiniz.
  Bu recovery writer waits olayını azaltmak için  flash recovery area file system ve storage birimini "tune" etmemiz gerekir.
  Özellikle, aşağıdakileri yapmanız gerekir:
 
    Flashback logları oldukça büyük olma eğiliminde olduğundan, bu dosyalara yazarken veritabanınıza extra CPU yükü getirir.
   İlk akla gelen şeylerden biri, flash recovery area yı daha hızlı bir file sisteme taşımaktır. Ayrıca, Oracle, ASM'ye dayalı file sistemlerini kullanmanızı önerir; çünkü yavaşlatmaya sebep verebilecek I/O lar işletim sistemi file caching e tabi tutulmazlar.
  
   • Flaş kurtarma alanını depoladığınız file sistemi için birden çok disk ağı yapılandırarak disk verimliliğini artırın.Bu flashback loglarının yazımını hızlandıracaktır.
  
    Depolama hacimlerini ideal olarak küçük sınır boyutlarıyla (örneğin, 128 KB) sınırlandırın.
  
   • LOG_BUFFER başlatma parametresini minimum 8 MB değerine ayarlayın; flashback database loglarına yazma için ayrılan bellek, LOG_BUFFER parametresinin ayarına bağlıdır.
  
  Nasıl Çalışır:

  - Oracle, redolog buffer durumunun aksine,Oracle Flashback Database ek yükü düşük tutmak için, flashback loglarına düşük aralıklarla flashback bufferı yazar.
Flashback buf free by RVWR wait event, oturumlar RVWR işlemi üzerinde beklerken oluşur.
RVWR işlemi, flashback bufferların içeriğini disk üzerindeki flashback loglarına yazar.
Bu süreç sırasında RIVER geride kaldığında, Flashback buffer doludur ve boş arabellekler verileri DML işlemleri ile değiştiren oturumlar için kullanılamaz.
Oturumlar, RVWR'nin bufferı geri yükleyerek içeriğini flashback loglarına yazarak beklemeye devam edecektir.
Yüksek RVWR bekleyişleri, I/O sisteminizin, RVWR'nin flashback tamponlarını diskteki flashback loglarına götürmesi gereken hızı destekleyemediğini belirtir.

Minimizing System Contention ( 10- Direct Path Read Wait Events )

Direct Path Read Wait Events

  - Direct path read ve direct path read temp events bekleme olayları, oturumlar SGA dan veri okumak yerine doğrudan PGA dan okumak için oluşan bekleme olaylarıdır.
  PGA dan veri okumak sorun değil, örneğin sorting gibi belirli işlemler için normal bir davranış.
  Direct path read ve direct path read temp events olayları genellikle gerçekleştirilen türlerin çok büyük olduğunda ve PGA'nın bu türlere uyum sağlayamadığında gösterir.
  - Bekleyen blokların dosya ID lerini almak için aşağıdaki komutu çalıştırın:

   SQL> select p1 "file#", p2 "block#", p3 "class#"
     from v$session_wait
     where event = 'direct path read temp';

  - P1 sütunu, okuma çağrısı için dosya ID sini gösterir. P2 sütununda BLOCK_ID blog başlangıcını, P3 sütununda da blokların sayısını gösterir.
  Daha sonra, bu dosya ID sini temporary tablespace ın tempfile ı olup olmadığını kontrol etmek için aşağıdaki sorgu çalıştıralım:

   SQL> select relative_fno, owner, segment_name, segment_type
     from dba_extents
     where file_id = &file
     and &block betgween block_id and block_id + &blocks - 1;
  - Direct read wait, diskte aşırı sort işlemi veya full table scan nedeniyle oluşabilir. Okunanların gerçekte ne olduğunu öğrenmek için, V$SESSION_WAIT
  viewının P1 sütununu (okunan çağrı için dosya ID) kontrol edin. Bunu yaparak, okumaların disk sort işlemi nedeniyle TEMP tablolarından veri okunmasından mı yoksa
  paralel slaveler tarafından full table scan yüzünden mi meydana gelip geldiğini öğrenebilirsiniz.

  - Direct read wait events olaylarına neden olanı diskte sort işlemi olarak belirlerseniz,
  PGA_AGGREGATE_TARGET parametresinin değerini yükseltin (Veya otomatik bellek yönetimi kullanıyorsanız bunun için minimum bir boyut belirtin)
  PGA boyutunu artırmak, sorgular large hash joins yaptığında iyi bir stratejidir, PGA large hash joins işlemlerini işlemek için yetersiz kalırsa, diskte aşırı I/O'ya neden olabilir.
  Bir tablo için high degree parallelism belirlediğinizde Oracle, paralel slavelerini kullanarak full table scan yapma eğilimindedir.
  I/O sistemi tüm paralel slavelerin üstesinden gelemezse, yüksek miktarda direct path read olayı ile karşılaşacaksınız.
  Bunun çözümü, söz konusu tablo veya tablolar için paralellik derecesini azaltmaktır. Ayrıca, uygun indexleri belirterek full table scan i  engelleyip engellenmediğini kontrol edin.

  Nasıl Çalışır:
  - Normalde, "sequential db read" veya "scattered db read" işlemi sırasında, veritabanı diskten SGA'ya veri okur.
  Direct path read ,SGA yı atlayarak diskten direk PGA'ya yapılan single veya multiblock okuma olayıdır.
  İdeal olarak, veri tabanı PGA'daki verilerin tümünün sorting işlemini yapmalıdır.
  Mevcut PGA'ya a huge sort uymuyorsa, Oracle sıralama verisinin bir bölümünü doğrudan diske yazar.
  Sunucu işlemi bu verileri diskten (PGA yerine) okurken "direct read" meydana gelir.

  - Direct path read event olayı, I/O sistemine aşırı yüklendiğinde ortaya çıkabilir; büyük olasılıkla tablolar için yüksek düzeyde bir paralellik ayarlamasının neden olan full table scan nedeniyle, veritabanının sunucuların işlem hızının gerektirdiği kadar bufferı yavaşlatmasına neden olur
  Burada iyi bir diske yazma stratejisi yardımcı olacaktır.
  Oracle'ın Automatic Storage Management (ASM) ı otomatik olarak verileri siler. Zaten ASM kullanmıyorsanız, veritabanınıza uygulamayı düşünün.

  - "Direct path write" ve "direct path write temp wait events" olayları "direct path read" ve "direct path read temp wait"  olaylarına benzer.
  Normalde, buffer cache den veri yazan DBWR'dir. Oracle, bir process data bufferlarına direk PGA'dan yazdığında direct path write kullanır.
  Veritabanınız disk ağır sortlar icra ediyorsa veya paralele DML işlemleri mevcutsa, bazen direct path write olaylarıyla karşılaşmayı bekleyebilirsiniz. Paralel bir CTAS (create table as select) veya direct path INSERT gibi işlemleri yürüttüğünüzde bu bekleme olayını da görebilirsiniz.
  Direct path read events olaylarında olduğu gibi, direct path write events olayları için çözüm beklemelere neyin bağlı olduğuna bağlıdır. Beklemeler çoğunlukla large sorts dan kaynaklanıyorsa, PGA_AGGREGATE_TARGET parametresinin değerini arttırmayı düşünebilirsiniz. Paralel DML gibi işlemler beklemelere neden oluyorsa, tüm diskler arasında I/O'nun düzgün bir şekilde yayılmasına dikkat edin ve ayrıca I/O sisteminin DML işlemleri sırasında yüksek dereceli paralellikleri işleyebildiğinden emin olmanız gerekir.

Minimizing System Contention ( 9- Read by Other Session Wait Events )

Read by Other Session Wait Events


  -  Read by other session wait event olayında "read" görünmesinin ana nedeni, aynı veri bloklarını, tablo veya index blokları olsun veya olmasın, birden çok session ın okumak istediği ve şu anda bu blokları okumakta olan session ın arkasında beklemek zorunda olduğudur. Bir session ı bekleyen data bloklarını aşağıdaki komutu çalıştırarak bulabilirsiniz:

   SQL> select p1 "file#", p2 "block#", p3 "class#"
     from v$session_wait
     where event = 'read by other session';
    
  - Beklenen bloğu  "blok#" sütunundan aldıktan sonra diğer oturum beklemelerine göre okumaya neden olan kesimleri (tablo veya index) belirlemek için aşağıdaki sorguda kullanabilirsiniz.
  
   SQL> select relative_fno, owner, segment_name, segment_type
     from dba_extents
     where file_id = &file
     and &block between block_id
     and block_id + blocks - 1;
    
  - Hot blokları ve ait oldukları segmentleri belirledikten sonra, bu veri bloklarını ve segmentleri kullanan sorguları tanımlamanız ve mümkünse bu sorguları ayarlamanız gerekir.
  Ayrıca, hot bloklardaki satırları silmeyi ve tekrar eklemeyi deneyebilirsiniz.

  - Hot blokların her birindeki veri miktarını azaltmak ve böylece bu bekleme türlerini azaltmak için, daha küçük bir blok boyutu olan yeni bir tablespace oluşturmaya ve segmenti bu tablo alanına taşımayı deneyebilirsiniz.
  Ayrıca low cardinality indexlerin kullanılıp kullanılmadığını kontrol etmek iyi bir fikirdir, çünkü bu tür indexler, veritabanını çok sayıda veri bloğunu buffer cache e getirecektir ve buda "read by other session wait event" sebeb verecektir.
  Mümkünse, low cardinality indexlerini high cardinality sütundaki bir dizinle değiştirin.

  Nasıl Çalışır:

  - Read by other session wait event olayı, bir veya daha fazla oturumun, aynı veri bloklarını diskten SGA'ya okumak üzere başka bir oturum beklediğini gösterir. Bu beklemelerin çok sayıda olması performansı yavaşlatacaktır.
  İlk hedefiniz, gerçek veri bloklarını ve blokların ait olduğu object leri tanımlamak olmalıdır.
  Örneğin, bu beklemeler, aynı index bloklarını okumaya çalışan birden fazla oturumdan kaynaklanabilir.
  Aynı tabloda aynı anda birden fazla oturum full table scan gerçekleştirmeye çalışıyor olabilir.

Constraint Disable-Enable

Disable Constraint BEGIN   FOR c IN   (SELECT c.owner, c.table_name, c.constraint_name    FROM user_constraints c, user_tables t    WHERE...