SQL Server事务失败并且表被锁定

时间:2017-03-22 06:37:01

标签: sql sql-server-2012

我的存储过程就像这样

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[Bid_Create]
    @BidType int,
    @ClientId int,
    @BidDate date,
    @EmailNotificationStatus int,
    @BidStatus int,
    @BidAmount int,
    @ProductId int
AS    
    DECLARE @highestBid int;
BEGIN
    BEGIN TRY
        BEGIN TRANSACTION

        SET NOCOUNT ON;

        SET @highestBid = (SELECT Max(wf_bid.BidAmount) AS HighestBitAmount 
                           FROM wf_bid 
                           WHERE wf_bid.ProductId = @ProductId)

        IF @highestBid is NULL OR @highestBid < @BidAmount
        BEGIN
            UPDATE wf_bid 
            SET BidStatus = '1' 
            WHERE Id = (SELECT TOP 1 id 
                        FROM [wf_bid] 
                        WHERE BidAmount = (SELECT MAX(BidAmount) 
                                           FROM [wf_bid] 
                                           WHERE ProductId = @ProductId 
                                             AND ClientId = @ClientId))


            INSERT INTO wf_bid (BidType, ClientId, BidDate, EmailNotificationStatus, BidStatus)
            VALUES (@BidType, @ClientId, @BidDate, @EmailNotificationStatus, @BidStatus)
        END

        COMMIT TRANSACTION
    END TRY
    BEGIN CATCH
        ROLLBACK TRANSACTION
    END CATCH
END

一切看起来都不错。但是一旦我运行它,表就会被锁定。表上没有其他查询可以工作(我认为这是因为事务没有提交)。

有人能指出这个查询有什么问题吗?我该如何解锁桌子呢?

1 个答案:

答案 0 :(得分:1)

  

但是一旦我运行它,表就会被锁定

这可能是由于更新占用了很多锁,这反过来可能是由于谓词不可靠。虽然这个更新锁(U)锁将在谓词不匹配时立即释放。您将遇到阻塞

另一个原因是,为什么此更新可能会阻止您的整个表格,这是因为此事务获得了超过5000个锁...

另一个原因可能是,在提交了这么多行后你的事务失败并且它必须做很多回滚工作

以上是我能想到的原因,你可以在哪里体验到桌子锁定的感觉

要解决此问题,您需要使用以下查询检查锁定blokcings

select resource_type,resource_Database_id,
request_mode,request_type,request_Status,request_session_id
 from sys.dm_tran_locks 
 where request_session_id=<<your update session id>>

你也会多次访问桌子,因为获得最大值,你可以像下面那样重写它

;with cte
as
(
select top (1) with ties  id,bidstatus from 
wf_bid 
where ProductId=@ProductId and ClientId=@ClientId)
order by 
row_number() over (partition by id order by bid_Amount desc)
)
update cte
set bidstatus=1