- Konu sahibi
- #1
Veritabanı deadlock hatası nasıl araştırılır?
Deadlock, iki veya daha fazla transaction’ın birbirinin tuttuğu kilidi bekleyerek ilerleyememesi durumudur. Hata kodu ve zamanı kaydedip motorun deadlock dökümüyle eşleştirin: hangi transaction hangi kaynağı tutuyor, hangi kaynağı bekliyor, işlemler hangi SQL cümlesinde ve hangi sırayla çalışıyor? Grafik yoksa önce veritabanının deadlock olayını ayrıntılı olarak kaydetmesini sağlayın; yalnızca uygulamadaki “timeout” mesajına bakmak yeterli değildir.
Deadlock nasıl oluşur?
Basit bir varsayımsal senaryoda iki transaction, aynı iki tabloyu ters sırada günceller:
- Transaction A,
Musterilertablosundaki 10 numaralı kaydı kilitler; sonraSiparislertablosundaki ilgili kaydı bekler. - Transaction B, aynı sipariş kaydını kilitler; sonra 10 numaralı müşteri kaydını bekler.
- A, B’nin kilidini; B de A’nın kilidini beklediği için ikisi de ilerleyemez.
- Veritabanı sistemi transaction’lardan birini deadlock kurbanı seçerek geri alır; diğer transaction devam edebilir.
Bu nedenle deadlock, tek başına “veritabanı bozuldu” anlamına gelmez. Genellikle aynı kaynaklara farklı sırayla erişen transaction’lar, gereğinden uzun açık kalan transaction’lar, geniş tarama yapan sorgular veya uygun olmayan indeksler birlikte etkili olur.
Araştırma adımları
- Uygulama logundan deadlock zamanını, transaction kimliğini, sorgu adını ve hangi isteğin yeniden denenmesi gerektiğini çıkarın. Bir timeout ile gerçek deadlock’u karıştırmayın; timeout, kilit beklemesinin süresi dolduğu için oluşabilir ve deadlock dökümü içermeyebilir.
- Veritabanı motorunun deadlock olayını kaydettiği tanılama kaydını açın veya mevcut kaydı bulun. PostgreSQL’de sunucu logundaki deadlock ayrıntıları, MySQL’de InnoDB deadlock dökümü incelenir. Üretimde ayrıntılı izlemeyi sınırsız süre açık bırakmadan, olayla ilişkilendirilebilecek şekilde kullanın.
- Deadlock grafiğinde her işlem için tutulan kilitleri, beklenen kilitleri, tablo veya indeks adını, transaction başlangıcını ve çalıştırılan SQL’i not edin. “Victim” olarak seçilen işlem yalnızca sonuçtur; asıl neden diğer işlemlerin kilit döngüsüdür.
- İki işlemin kaynaklara erişim sırasını karşılaştırın. Bir işlem önce müşteri sonra sipariş, diğeri önce sipariş sonra müşteri erişiyorsa ortak erişim sırasını belirleyin.
- Transaction kapsamını küçültün. Kullanıcıdan veri bekleme, ağ çağrısı, dosya işlemi veya uzun hesaplama transaction açıkken yapılmamalıdır. Gerekli okumaları ve yazmaları mümkün olduğunca kısa bir bölümde tamamlayın.
- İlgili sorguların yürütme planını ve indekslerini kontrol edin. Eksik indeks, daha fazla satırın taranmasına ve daha geniş kilitlerin daha uzun süre tutulmasına neden olabilir; ancak sırf deadlock gördüğünüz için rastgele indeks eklemeyin.
- Düzeltmeden sonra aynı iş yükünü ve eşzamanlılığı temsil eden bir testte yeniden izleme yapın. Deadlock kaybolduysa sorgu sırası, transaction süresi ve kilit kapsamındaki değişikliği kayda geçirin.
MySQL/InnoDB için gerekli PROCESS yetkisiyle şu salt okunur komut son deadlock dökümünü gösterir:
Kod:
SHOW ENGINE INNODB STATUS;
LATEST DETECTED DEADLOCK bölümü yalnız son olayı gösterebilir; uygulamadaki olay saatiyle eşleştirin. Tüm olayları kaydetmek için innodb_print_all_deadlocks ayrı bir yönetim ayarıdır; mevcut değer kaydedilerek dar süreli kullanılmalı, sonra önceki politikasına dönülmelidir. InnoDB 1213 deadlock hatasında bütün transaction geri alınır; 1205 lock-wait-timeout ise varsayılan olarak yalnız bekleyen ifadeyi geri alabilir. Retry öncesinde transaction durumunu açıkça düzeltin.
Deadlock grafiğini yorumlama
Bir grafikte A işleminin tuttuğu kaynak B’nin bekleme kaynağı, B işleminin tuttuğu kaynak da A’nın bekleme kaynağıysa döngü vardır. Yalnızca “hangi sorgu kurban oldu?” sorusunu cevaplamak çözüm değildir; kurban seçimi çoğu zaman maliyet veya transaction özelliklerine göre yapılır ve kök nedeni göstermeyebilir.
Tanılama sırasında şu bilgileri yan yana koymak yararlıdır:
| İncelenecek bilgi | Ne aranır? | Olası karar |
|---|---|---|
| Erişim sırası | Aynı tablolar ters sırada mı okunuyor veya güncelleniyor? | Tüm kod yollarında ortak sıra kullanılır. |
| Transaction süresi | Kilitler gereğinden uzun mu tutuluyor? | Transaction daraltılır ve dış işlemler kapsamdan çıkarılır. |
| Sorgu planı | Geniş tarama veya beklenmeyen kilit kapsamı var mı? | Sorgu ve indeks tasarımı birlikte gözden geçirilir. |
| İzolasyon ve kilit türü | Beklenen okuma-yazma davranışıyla uyumlu mu? | İzolasyon ayarı bilinçli olarak değerlendirilir; rastgele gevşetilmez. |
Kalıcı çözüm ve uygulama tarafı
En sağlam çözüm, aynı kaynaklara erişen tüm transaction’larda tutarlı bir sıra kullanmaktır. Buna ek olarak transaction’ları kısa tutun, sorguların doğru satırları hedeflemesini sağlayın ve büyük toplu işlemleri uygun parçalara bölmeyi değerlendirin. Uygulama katmanında deadlock kurbanı için sınırlı ve kontrollü yeniden deneme uygulanabilir; transaction her denemede baştan açılmalı, geri alma tamamlanmadan tekrar denenmemeli ve tüm hatalar gizlenmemelidir. Yeniden deneme kök nedeni düzeltmez, yalnızca geçici çakışmanın kullanıcıya yansımasını azaltır.
Sık yapılan hatalar
Sadece hatayı yeniden denemek: Olay kaydı alınmıyorsa kaynak sırası ve kilit döngüsü görünmez.
Transaction’ı gereksiz büyütmek: Bir transaction içinde dış servis çağırmak veya kullanıcı işlemi beklemek kilitlerin yaşam süresini uzatır.
Her sorunu indeksle çözmeye çalışmak: İndeks taramayı azaltabilir, fakat ters erişim sırasını veya uzun transaction’ı tek başına düzeltmez.
Sık sorulan sorular
Deadlock ile lock timeout arasındaki temel fark nedir?
Deadlock’ta kilit bekleyen işlemler arasında döngü vardır ve motor işlemlerden birini sonlandırır. Timeout’ta işlem, izin verilen bekleme süresi dolduğu için başarısız olabilir; döngü bulunması şart değildir.
Deadlock kurbanı olan transaction yeniden çalıştırılabilir mi?
İşlem idempotent tasarlanmışsa ve transaction tamamen geri alınmışsa kontrollü biçimde yeniden denenebilir. Yan etkili dış işlemler varsa otomatik retry öncesinde aynı işin iki kez yapılmayacağından emin olunmalıdır.
İzolasyon seviyesini düşürmek kalıcı çözüm müdür?
Genellikle hayır. Bu yaklaşım bazı okuma kilitlerini azaltabilir, ancak kirli veya tutarsız veri okuma gibi yeni sonuçlar doğurabilir. Önce erişim sırası, transaction kapsamı ve sorgu planı incelenmelidir.