SQL Server 2005死锁问题

时间:2009-09-18 14:02:21

标签: sql sql-server-2005 deadlock

我在尝试锁定某些记录时遇到了死锁问题,因此没有进程(Windows服务)选择要为其提供服务的项目,然后更新状态然后返回记录集。

请你告诉我为什么在调用此proc时遇到死锁问题?

CREATE PROCEDURE [dbo].[sp_LoadEventsTemp]
(
   @RequestKey varchar(20),
   @RequestType varchar(20),
   @Status varchar(20),
   @ScheduledDate smalldatetime = null
)
AS
BEGIN
   declare @LoadEvents table
   (
      id int
   )

   BEGIN TRANSACTION

   if (@scheduledDate is null)
   Begin
      insert into @LoadEvents (id)
      (
         Select eventqueueid FROM eventqueue
         WITH (HOLDLOCK, ROWLOCK)
         WHERE requestkey = @RequestKey
         and requesttype = @RequestType
         and [status] = @Status
      )
   END
   else
   BEGIN
      insert into @LoadEvents (id)
      (
         Select eventqueueid FROM eventqueue
         WITH (HOLDLOCK, ROWLOCK)
         WHERE requestkey = @RequestKey
         and requesttype = @RequestType
         and [status] = @Status
         and (convert(smalldatetime,scheduleddate) <= @ScheduledDate)
      )
   END

   update eventqueue set [status] = 'InProgress'
   where eventqueueid in (select id from @LoadEvents)

   IF @@Error 0
   BEGIN
      ROLLBACK TRANSACTION
   END
   ELSE
   BEGIN
      COMMIT TRANSACTION
      select * from eventqueue
      where eventqueueid in (select id from @LoadEvents)
   END
END

提前致谢。

3 个答案:

答案 0 :(得分:1)

您是否将非聚集索引定义为:

CREATE NONCLUSTERED INDEX NC_eventqueue_requestkey_requesttype_status
    ON eventqueue(requestkey, requesttype, status)
         INCLUDE eventqueueid

和另一个关于eventqueueid?

BTW将列scheduleddate转换为smalldatetime类型将阻止在该列上使用任何索引。

答案 1 :(得分:1)

首先,当您运行SQL Server时,我建议您安装Performance Dashboard,这是一个非常方便的工具,用于识别当前在服务器上进行的锁定。

Performance Dahsboard Link

其次,使用SQL事件探查器(已安装)跟踪您的SQL Server,并确保在事件选择上选择项目锁定&gt;死锁图将显示导致死锁的原因。

你必须清楚地知道什么是死锁才能开始排除故障。 当对DB上的任何表或行进行任何访问时,都会进行锁定。

允许调用SPID 51和SPID 52(SPID = SQL进程ID)

SPID 51锁定Cell A

SPID 52锁定Cell B

如果在同一事务SPID 51请求Cell B,它将等待SPID 52直到它释放它。

如果在同一事务SPID 52请求单元A,则会出现死锁,因为这种情况永远不会完成(51等待52和52为51)

告诉你要排除故障并不容易,但你要深入挖掘才能找到解决方案

答案 2 :(得分:0)

当不同的资源被锁定在不同订单的不同交易中时,死锁最常发生(根据我的经验)。

想象一下使用资源A和B的2个进程,但是以不同的顺序锁定它们 - 进程1锁定资源A,然后锁定资源B
- 进程2锁定资源B,然后锁定资源A

以下可能成为可能:
- 进程1锁定资源A
- 进程2锁定资源B
- 进程1尝试锁定资源B,然后停止并等待进程2拥有它 - 进程2尝试锁定资源A,然后停止并等待进程1拥有它 - 两个程序都在等待,死锁

在你的情况下,由于死锁(我猜的更新?)以及引用该表的任何其他进程,我们需要确切地看到SP落在哪里。它可能是一个触发器或其他东西,然后在另一个表上而不是你正在更新的表上陷入僵局。


我要做的是使用SQL Server 2005's OUTPUT syntaxt来避免使用交易......

UPDATE
  eventqueue
SET
  status = 'InProgress'
WHERE
      requestkey  = @RequestKey
  AND requesttype = @RequestType
  AND status      = @Status
  AND (convert(smalldatetime,scheduleddate) <= @ScheduledDate OR @ScheduledDate  IS NULL)
OUTPUT
  inserted.*