对可能在SERIALIZABLE锁下的数据进行SELECT

时间:2016-10-01 18:29:56

标签: sql-server

我有一部分应用程序不断更新表行(1-100行)中的值。 由于这种数据完整性很重要,我在读取和更新这些行的函数中使用SERIALIZABLE锁定事务。

现在我的问题是,如果我在一个事务当前使用的行上执行一个简单的只读SELECT(没有锁定),我可能会得到一个DEADLOCK异常吗? 那么这意味着即使在简单的SELECT情况下,我仍然需要DEADLOCK的重试机制吗?

1 个答案:

答案 0 :(得分:3)

现在我知道你的具体业务场景是什么(来自评论),这就是你如何做一些像你提出的建议,而不必实现可序列化的隔离

CREATE PROCEDURE [dbo].[updateUserState] (@UserID int)
AS
BEGIN
    SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
    BEGIN TRANSACTION

        SELECT [State]
        FROM [dbo].[UserState] WITH (UPDLOCK)
        WHERE [UserID] = @UserID;

        IF ([State] = 'logged out')
        BEGIN
            UPDATE [us]
            SET [State] = 'logged in'
            FROM [dbo].[UserState] AS [us]
            WHERE [UserID] = @UserID;
        END

    COMMIT TRANSACTION
END

请注意,这是简化的,但提出了主要想法。 UPDLOCK语句上的SELECT提示是关键。它说“尝试选择数据,因为我将要做更新(你就是这样!稍后)并保持直到交易结束”。在您的示例中,如果T2进入且T1仍在运行,则T2将无法获取更新锁定,因此将等待T1完成(成功或否)。另请注意,明确设置事务隔离级别只是为了完整性; READ COMMITTED是SQL Server中的默认设置。