我使用以下存储过程获得间歇性死锁。它每分钟运行一次。它已经生产了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
答案 0 :(得分:0)
我怀疑这是一个特定锁定的问题比你的连接愿意等待的时间长。没有东西可以杀掉长时间运行的事务,在这里,你会遇到这种情况,因为当连接超时时,SQL Server强制等待结束&amp;作为死锁受害者杀死传入的锁。
长话短说:某些进程(不是这里详述的进程)锁定表,导致死锁。
检查遇到死锁时还有其他问题 - 是否有正在运行的备份或其他锁定此表的内容?