在捕获块中选择未提交的读取

时间:2018-11-30 12:14:54

标签: sql tsql error-handling try-catch database-deadlocks

我试图找到一种解决方法,以解决UPDATE和SELECT语句之间的死锁,该死锁很难重现,但发生在生产服务器上。默认情况下,SELECT语句被终止,这是首选。我要处理的方式是:

  • 像往常一样运行SELECT
  • 失败时,运行SELECT WITH(NOLOCK)

要模拟死锁,我使用此example。我将第4点修改为:

BEGIN
    BEGIN TRY
        SELECT 'TRYING TO SELECT 1'
        select value, * from B where value = 1 or id = 1
        SELECT 'SELECT 1 SUCCESFUL'
    END TRY
    BEGIN CATCH
        SELECT 'TRYING TO SELECT 2'
        select value, * from B with (NOLOCK) where value = 1 or id = 1
        SELECT 'SELECT 2 SUCCESFUL'
    END CATCH
END

我得到的结果是:

  • 尝试选择1
  • SELECT 1的结果(为什么?)
  • 尝试选择2
  • SELECT 2的结果
  • 选择2个成功
  • 错误:批处理结束时检测到不可提交的事务。交易已回滚。

我真的不明白为什么看到SELECT 1的结果。但是,如果我用BEGIN TRANSACTION / ROLLBACK包装查询,如下所示:

BEGIN
        BEGIN TRANSACTION
        BEGIN TRY
            SELECT 'TRYING TO SELECT 1'
            select value, * from B where value = 1 or id = 1
            COMMIT TRANSACTION;
            SELECT 'SELECT 1 SUCCESFUL'
        END TRY
        BEGIN CATCH
            IF @@trancount > 0 ROLLBACK TRANSACTION
            SELECT 'TRYING TO SELECT 2'
            select value, * from B with (NOLOCK) where value = 1 or id = 1
            SELECT 'SELECT 2 SUCCESFUL'
        END CATCH
END

哪些回滚了挂起的UPDATE事务,这是我不想要的。

如果没有发生死锁,则预期结果是仅执行第一个查询,如果发生死锁,则仅执行第二个查询。

PS。是的,我知道读取未提交的数据可能导致读取不干净和数据不一致。

0 个答案:

没有答案