2012-08-28 17 views
5

Kilitlenmelerden kaçınmaya ve birden çok hizmetten gelen istekleri eşzamanlamaya çalışırken, ROWLOCK, READPAST kullanıyorum. Sorum, CTE'de bir alt sorgu ve bir güncelleme bildirimi içeren bir sorguya nereye yerleştirmeliyim? Bir anahtar nokta var mı yoksa üç yer de mi (aşağıda) olmalı? Ya da SADECE güncellenecek satırları seçebilmem için böyle bir sorgu yazmanın daha iyi bir yolu var.ROWLOCK, CTE, Alt sorgu ve Güncelleme ile READPAST nerede kullanılır?

alter proc dbo.Notification_DequeueJob 
    @jobs int = null 
as 

    set nocount on; 
    set xact_abort on; 

    declare @now datetime 
    set @now = getdate(); 

    if(@jobs is null or @jobs <= 0) set @jobs = 1 

    ;with q as (
     select 
      *, 
      dense_rank() over (order by MinDate, Destination) as dr 
     from 
     (
      select *, 
       min(CreatedDt) over (partition by Destination) as MinDate 
      from dbo.NotificationJob with (rowlock, readpast) 
     ) nj 

    where (nj.QueuedDt is null or (DATEDIFF(MINUTE, nj.QueuedDt, @now) > 5 and nj.CompletedDt is null)) 
    and (nj.RetryDt is null or nj.RetryDt < @now) 
    and not exists(
     select * from dbo.NotificationJob 
     where Destination = nj.Destination 
     and nj.QueuedDt is not null and DATEDIFF(MINUTE, nj.QueuedDt, @now) < 6 and nj.CompletedDt is null) 
    ) 
    update t 
     set t.QueuedDt = @now, 
      t.RetryDt = null 
    output 
     inserted.NotificationJobId, 
     inserted.Categories, 
     inserted.Source, 
     inserted.Destination, 
     inserted.Subject, 
     inserted.Message 
    from q as t 
    where t.dr <= @jobs 
go 

cevap

1

Elimde bir yanıt yok, ancak daha fazla bilgi edinebileceğiniz yollar var.

Yazdığınız kod makul görünüyor. Proc için gerçek sorgu planının incelenmesi, SQL Server'ın da makul bir sorgu planı oluşturabileceğini doğrulamaya yardımcı olabilir.

QueuedDt ve CompletedDt içeren NotificationJob.Destination üzerinde bir diziniz yoksa, not exists alt sorgusu tüm tablodaki paylaşılan kilitleri alabilir. Bu eşzamanlılık için korkutucu olurdu.

İşlemcinin kilit aldığında nasıl davranacağını gözlemleyebilirsiniz. Bir yol, trace flag 1200'u geçici olarak açmak, proc'unuzu çağırmak ve ardından bayrağı kapatmaktır. Bu, proc'un ne tür kilitler aldığı hakkında çok bilgi üretecektir. Bilgi miktarı performansı ciddi şekilde etkiler, bu yüzden bu bayrağı bir üretim sisteminde kullanmayın.

dbcc traceon (1200, -1) -- print detailed information for every lock request. DO NOT DO THIS ON A PRODUCTION SYSTEM! 
exec dbo.Notification_DequeueJob 
dbcc traceoff (1200, -1) -- turn off the trace flag ASAP