使用TABLOCK,XLOCK命令在Microsoft SQL Server 2008上发生间歇性死锁

时间:2012-10-15 16:35:56

标签: sql sql-server deadlock

我使用以下存储过程获得间歇性死锁。它每分钟运行一次。它已经生产了1年以上,我们通常不会出现这个错误,但它有时会突然出现......它在我们的一个环境中每天抛出3到5次异常...它与其他实例的环境相同没有抛出错误。存储过程是这样的,它一次只能运行一次,但也许我们这样做的方式不合适?

这是错误:

  

System.Web.HttpUnhandledException:抛出了类型为“System.Web.HttpUnhandledException”的异常。 --->   System.Data.SqlClient.SqlException:事务(进程ID 60)是   锁定资源与另一个进程死锁并已被选中   作为死锁的受害者。重新运行该交易。

这是存储过程:

 SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[requestUpdate]
AS
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

BEGIN TRAN
    DECLARE @StartDate datetime,
            @EndDate datetime,
            @Throttle bit,
            @Expired bit

    SELECT @Throttle = 0
    SELECT @Expired = 0

    SELECT TOP 1 @StartDate = uq.StartDate, @EndDate = uq.EndDate
      FROM UpdateQueue uq WITH(TABLOCK,XLOCK)
     ORDER BY ID DESC

    -- PREVENT ANOTHER REQUEST IF THIS SP HAS BEEN
    -- CALLED IN THE LAST FORTY SECONDS.
    IF DATEADD(SECOND,-40,GETDATE()) < @StartDate
    BEGIN
      SELECT @Throttle = 1
    END

    -- CREATE ANOTHER REQUEST IF THE CURRENT ONE
    -- HAS NOT COMPLETED IN THE LAST FIVE MINUTES.
    IF @StartDate <= DATEADD(MINUTE,-5,GETDATE())
    BEGIN
      SELECT @Expired = 1
    END

    -- HAS THE CURRENT REQUEST EXPIRED?
    IF @EndDate IS NULL AND @Expired = 1
    BEGIN
      INSERT INTO UpdateQueue (RequestID, StartDate) OUTPUT 'EXPIRED' AS Result, INSERTED.RequestID AS RequestID
      VALUES (NEWID(), GETDATE())
    END

    -- HAS THE CURRENT REQUEST COMPLETED AND YOU ARE NOT THROTTLING
    -- OR HAVE THERE NOT BEEN ANY REQUESTS YET?
    ELSE IF (@EndDate IS NOT NULL AND @Throttle = 0) OR @StartDate IS NULL
    BEGIN
      INSERT INTO UpdateQueue (RequestID, StartDate) OUTPUT 'STARTED' AS Result, INSERTED.RequestID AS RequestID
      VALUES (NEWID(), GETDATE())
    END

    -- Running
    ELSE
    BEGIN
      SELECT 'RUNNING' AS Result, NULL AS RequestID
    END

COMMIT

1 个答案:

答案 0 :(得分:0)

我怀疑这是一个特定锁定的问题比你的连接愿意等待的时间长。没有东西可以杀掉长时间运行的事务,在这里,你会遇到这种情况,因为当连接超时时,SQL Server强制等待结束&amp;作为死锁受害者杀死传入的锁。

长话短说:某些进程(不是这里详述的进程)锁定表,导致死锁。

检查遇到死锁时还有其他问题 - 是否有正在运行的备份或其他锁定此表的内容?