Forum
Öncelikle selamlar...
Yazmış olduğum birkaç trigger den dolayı bazen sayfalarımda deadlock hatası alıyorum. Sql server üzerinde bu gibi hataları kapatabilirmiyim.
Tşkler...
Kapatmak derken?
ALTER TRIGGER [dbo].[FotoIzlenmeSayisi]
ON [dbo].[tblFotoLog]
AFTER INSERT,DELETE
AS
BEGIN
Declare @FotoID int
Select @FotoID = fldFoto From Inserted
Declare @IzlenmeSayisi int
Select @IzlenmeSayisi = Count(fldID) From tblFotoLog Where fldFoto = @FotoID
Declare @ZiyaretciSayisi int
Select @ZiyaretciSayisi = Count(DISTINCT fldUye) From tblFotoLog Where fldFoto = @FotoID
Update tblFotograf Set fldIzlenmeSayisi = @IzlenmeSayisi , fldZiyaretciSayisi = @ZiyaretciSayisi Where fldID = @FotoID
END
böyle bir trigger yazdım fakat tblFotoLog tablomda yaklaşık 4 milyona yakın kayıt var. her sayfa açılışında bu trigger işliyor bazen zaman aşımından olsa gerek diye düşünüyorum aşağıdaki gibi bir hata alıyorum.
[Microsoft][ODBC SQL Server Driver][SQL Server]Transaction (Process ID 98) was deadlocked on lock | communication buffer resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
bu hatayı nasıl çözebilirim veya @@ERROR diye bir t-sql komutu görmüştüm hatayı görüp uyarı vermeden devam ettirebilirmiyim.
deadlock konusunda biraz bilgi vereyim önce istersen.
deadlock, farklı kaynakları locklamış ve karşılıklı olarak locklanan kaynakları birinin diğerini beklediği durumda oluşur. Deadlock kelime manasından da anlaşılabileceği gibi ölümcül kitlenmedir ve 1 prosess kurban seçilmediği sürece devam edemez.
Biraz karışık oldu galiba örnek verelim.
A ve B diye 2 prosess imiz olsun. Ve sırasıyla şu işlemleri yapsınlar
A = 1. kaynağı lockladı
B = 2.kaynağı lockladı
A = 2. kaynağa erişmek istiyor ama B lockladığı için B nin işini bitirmesini bekliyor.
B = 1. kaynağa erişmek istiyor ama B lockladığı için A nin işini bitirmesini bekliyor.
İşte böyle bir durumda A ve B sonsuza kadar bekleyecektir. SQL Server Database Engine bu arkadaşlar sonsuza kadar beklemesin diye aralarından birini victim yani kurban seçerek rollback yapar ve diğerinin işine devam etmesini sağlar.
Victim algoratimasıda rollback i en az maliyetli olanın rollback edilmesi şeklindedir.
Bu ön bilgiden sonra gelelim deadlock'ın çözümüne.
Üzülerek söylüyorum ki deadlock ın kesin bir çözümü yoktur. Fakat aşağıdaki işlemler deadlock oluşma ihtimalini azaltacaktır.
- Index kullanımını gözden geçiriniz. Uzun süren sorgular transaction larında uzun sürmesine sebep olacağından deadlock ihtimalini arttıracaktır.
- Transaction larınızı kısa tutmaya çalışınız.
- SP ve Function gibi objeler içerisinde objelere aynı sırayla erişiniz.
- update scriptlerinde select ile update in index path lerini farklı yapmaya çalışınız.
Bunlar standart deadlock azaltma yöntemleri. Eğer yeterli olmazsa deadlock graph üzerinde analiz yapmak gerekecektir.
Turgay bey vermiş olduğunuz bilgiler için çok teşekkür ediyorum. Az çok olaya müdahil olabildim. Aklıma şöyle bir çözüm geldi aslında.
Msdn kütüphanesinde waitfor diye bir komut gördüm. Bu deadlock hatasını ard arda yapılan sorgulardan alıyorum. waitfor ile bekleme yapsam çözüme ulaşabilirmiyim acaba.
kesinlikle garantisi olmayacaktır.
şöyle düşün. 2 prosess aynı anda başladı ve aynı süre waitfor da bekledi. Gene deadlock a sebep olacaktır.
Benim sana tavsiyem index ler üzerine yoğunlaşmandır.
Oda olmadı son çare olarak deadlock hatasını try catch ile yakalayıp işlemi yapan script i bir kez daha çalıştırmaktır. Çünkü deadlock a yakalanan script 2.çalışmaya %99 oranında sorunsuz geçecektir. Ama bu yöntem de pek optimum bir yöntem değildir.
Teşekkür ederim çözüme ulaştırdığımda yazacağım.
Profiler' da deadlock ı izleyip deadlock ın kaynağını bulup iyileştirme yapabilirsiniz.
-Bekletmeleri azaltmak için Turgay'ın da bahsettiği gibi indexler gözden geçirilmeli
-Mimariye uygunsa nolock yada readpast table hintleri kullanılabilir.
-Aynı page lerin farklı kaynaklar tarafından aynı anda kullanımı azaltmak için fillfactor değerleri değiştirilebilir(page sayısını artırarak).