我有一个名为Banners
的表,其中包含BID
列,impressions
等等...
另外,我创建了StoredProcedure
,这是在网页加载上执行的。
存储过程
DECLARE @slot int
DECLARE @final varchar(MAX)
DECLARE @URL varchar(MAX)
DECLARE @ID varchar(MAX)
set @slot =0
SET @URL='';
SET @ID=0
SET @final='';
BEGIN
WHILE(@slot <= 6)
BEGIN
SET @slot= @slot+1
IF EXISTS(select BID from Banners (NOLOCK) where Slot=@slot AND SectionID =199 AND UserType in (@IsAnonymous,2) AND Enabled=1)
BEGIN
SET @final = (select TOP 1 '<div class=''sidebar-img''><a href ='''+ URL +''' id='''+CONVERT(varchar(10),BannerID)
+''' target=''_blank'' onclick=''Click(this)'';><img alt='''+Alt+''' src='''+BannerImage+''' height=''250'' width=''250''></a></div>'
FROM Banners (NOLOCK) where Slot=@slot AND Enabled=1 AND UserType in (@IsAnonymous,2)
AND SectionID =199
ORDER BY CHECKSUM(NEWID()))
IF(@final<>'')
BEGIN
SET @URL = @URL + @FINAL
SET @ID =(select replace( (select SUBSTRING(@final,charindex(' id=',@final)+5,4)),'''',''));
UPDATE Banners set impressions +=1 where BID=CONVERT(INT,@ID); <-- **this causes DEADLOCK**
END
ELSE
SET @URL = @final
END
ELSE
BEGIN
CONTINUE
END
END
SET @BannerHTML = @URL
END
deadlock issue
主要发生update statement
,我们正在更新Banners Table
。
请告诉我任何阻止Deadlock
的建议。
答案 0 :(得分:0)
我宁愿避免像你设计的那样构造。
首先,我认为您的对象Mercola_Banners
是一个使用您的表Banners
的视图,对吧?这可能会导致死锁。
无论如何,如果你有一个像横幅这样的表,我会避免直接更新它,这些表经常更新。
我认为你有两种选择。
OPTIMISTIC LOCKING
,它会使用一些tempdb来存储行的版本。在这种情况下,每个事务都可以使用不同版本的行。这意味着,如果您的交易运行,它可能会使用您的第一行。更新Banners表后,它会创建第二个版本。如果发生下一页加载,它将使用该行的第二版并将其更新为版本3。如果第一个事务结束,则不再引用版本1,它将被删除。 但,它可能会导致一些错误的更新,如果您几乎同时运行两个事务,它们可以相互重叠。示例:事务1启动,读取版本1.事务2启动,也读取版本1。事务1将行更新为版本2(将展示次数更新为2)。在下一步中,事务2生成另一行作为版本3(它还将印象从1更新为2)。最后,事务2和3结束,最后只存在版本3。这意味着您有2次展示,而不是真正的3次展示。这对您来说可能是一个问题。impressions
- 列。更新行后,您可以从登台表中删除行。这样您就可以解耦更新。在更新期间,您可能会导致独占锁定,从而阻止从banners
- 表中读取。插入只会导致独占的行锁,这不会造成太大的伤害。