Stack Overflow SQL Server 2005 veritabanında bazı tehlikeli ancak nadir görülen kilitlenme durumları görüyoruz.
Profil oluşturucuyu ekledim , kilitlenme sorunlarının giderilmesiyle ilgili bu mükemmel makaleyi kullanarak bir izleme profili oluşturdum ve bir dizi örnek yakaladım. İşin garibi , çıkmaza giren yazının her zaman aynı olmasıdır :
UPDATE [dbo].[Posts]
SET [AnswerCount] = @p1, [LastActivityDate] = @p2, [LastActivityUserId] = @p3
WHERE [Id] = @p0
Diğer kilitlenme ifadesi değişiklik gösterir, ancak genellikle postalar tablosunun bir tür önemsiz, basit okunmasıdır . Bu her zaman çıkmazda ölür. İşte bir örnek
SELECT
[t0].[Id], [t0].[PostTypeId], [t0].[Score], [t0].[Views], [t0].[AnswerCount],
[t0].[AcceptedAnswerId], [t0].[IsLocked], [t0].[IsLockedEdit], [t0].[ParentId],
[t0].[CurrentRevisionId], [t0].[FirstRevisionId], [t0].[LockedReason],
[t0].[LastActivityDate], [t0].[LastActivityUserId]
FROM [dbo].[Posts] AS [t0]
WHERE [t0].[ParentId] = @p0
Tamamen açık olmak gerekirse, yazma / yazma kilitlenmeleri değil, okuma / yazma görüyoruz.
Şu anda LINQ ve parametreli SQL sorgularının bir karışımına sahibiz. with (nolock)
Tüm SQL sorgularına ekledik . Bu bazılarına yardımcı olmuş olabilir. Ayrıca dün düzelttiğim, her seferinde 20 saniyeden fazla süren ve bunun üzerine her dakika çalışan tek (çok) kötü yazılmış bir rozet sorgumuz vardı. Bazı kilitleme sorunlarının kaynağının bu olduğunu umuyordum!
Ne yazık ki, yaklaşık 2 saat önce başka bir kilitlenme hatası aldım. Aynı kesin belirtiler, aynı suçlu yazısı.
Gerçekten tuhaf olan şey, yukarıda gördüğünüz kilitleme yazma SQL deyiminin çok özel bir kod yolunun parçası olmasıdır. O var sadece yeni cevap bir soruya eklendiğinde infaz - yeni cevap sayısı ve en son tarih / kullanıcı ile ebeveyn soru günceller. Bu, elbette, yaptığımız muazzam okuma sayısına göre o kadar yaygın değil! Anladığım kadarıyla, uygulamanın hiçbir yerinde çok sayıda yazma yapmıyoruz.
NOLOCK'un devasa bir çekiç olduğunun farkındayım, ancak burada yaptığımız sorguların çoğunun o kadar doğru olması gerekmiyor. Kullanıcı profilinizin birkaç saniye eski olması umrunda mı?
NOLOCK'u Linq ile kullanmak, Scott Hanselman'ın burada tartıştığı gibi biraz daha zor .
Kullanma fikri ile flört ediyoruz
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
temel veritabanı bağlamında, böylece tüm LINQ sorgularımız bu kümeye sahip olur. Bu olmadan, yaptığımız her LINQ çağrısını (bunların büyük çoğunluğu olan basit okuma çağrılarını) çirkin olan 3-4 satırlık bir işlem kodu bloğunda sarmamız gerekir.
Sanırım SQL 2005'teki önemsiz okumaların yazma işlemlerini çıkmaza sokması biraz hayal kırıklığına uğradım. Yazma / yazma kilitlenmelerinin büyük bir sorun olduğunu görebiliyordum, ancak okuyor? Burada bir bankacılık sitesi işletmiyoruz, her seferinde mükemmel doğruluğa ihtiyacımız yok.
Fikirler? Düşünceler?
Her işlem için yeni bir LINQ to SQL DataContext nesnesinin örneğini mi oluşturuyorsunuz yoksa tüm çağrılarınız için aynı statik bağlamı mı paylaşıyorsunuz?
Jeremy, temel Denetleyicide çoğunlukla bir statik veri içeriğini paylaşıyoruz:
private DBContext _db;
/// <summary>
/// Gets the DataContext to be used by a Request's controllers.
/// </summary>
public DBContext DB
{
get
{
if (_db == null)
{
_db = new DBContext() { SessionName = GetType().Name };
//_db.ExecuteCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED");
}
return _db;
}
}
Her Denetleyici için veya Sayfa başına veya daha sık yeni bir bağlam oluşturmamızı tavsiye ediyor musunuz?