Sql server 2008 在哪里使用ROWLOCK、带CTE的readpass、子查询和更新?

Sql server 2008 在哪里使用ROWLOCK、带CTE的readpass、子查询和更新?,sql-server-2008,common-table-expression,rowlocking,Sql Server 2008,Common Table Expression,Rowlocking,为了避免死锁和同步来自多个服务的请求,我使用了ROWLOCK,readpass。我的问题是,在包含CTE、子查询和CTE上的update语句的查询中,应该将其放在哪里?是否有一个关键点,或者三个地方都应该在下面?或者也许有更好的方法来编写这样的查询,这样我就可以只选择要更新的行 alter proc dbo.Notification_DequeueJob @jobs int = null as set nocount on; set xact_abort on;

为了避免死锁和同步来自多个服务的请求,我使用了ROWLOCK,readpass。我的问题是,在包含CTE、子查询和CTE上的update语句的查询中,应该将其放在哪里?是否有一个关键点,或者三个地方都应该在下面?或者也许有更好的方法来编写这样的查询,这样我就可以只选择要更新的行

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  

我手头上没有答案,但有很多方法可以让你学到更多

你写的代码似乎很合理。检查过程的实际查询计划可能有助于验证SQL Server是否也可以生成合理的查询计划

如果NotificationJob.Destination上没有包含QueuedDt和CompletedDt的索引,not exists子查询可能会获取整个表上的共享锁。这对于并发性来说是可怕的

您可以观察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