5

デッドロックを回避し、複数のサービスからの要求を同期するために、私はROWLOCK、READPASTを使用しています。私の質問は、CTE、サブクエリ、およびCTEの更新ステートメントを含むクエリのどこに配置する必要があるかということです。重要な場所は1つありますか、それとも3か所すべてにあるべきですか(下)。または、更新される行のみを選択できるように、このようなクエリを作成するためのより良い方法があるかもしれません。

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  
4

1 に答える 1

1

手元に答えはありませんが、もっと学ぶ方法はあります。

あなたが書いたコードは妥当なようです。プロシージャの実際のクエリプランを調べると、SQLServerが適切なクエリプランを生成できることも確認できる場合があります。

QueuedDtとCompletedDtを含むNotificationJob.Destinationのインデックスがない場合、サブクエリはnot existsテーブル全体の共有ロックを取得する可能性があります。それは並行性にとって恐ろしいことです。

ロックを取得したときのprocの動作を確認できます。1つの方法は、トレースフラグ1200を一時的にオンにし、procを呼び出してから、フラグをオフにすることです。これにより、procが取得しているロックに関する多くの情報が生成されます。情報の量はパフォーマンスに深刻な影響を与えるため、本番システムではこのフラグを使用しないでください。

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
于 2012-10-05T14:08:45.003 に答える