由于隔离级别不同导致的SQL Server事务错误

时间:2018-01-15 12:40:59

标签: sql-server transactions

我创建了以下存储过程,以便检查事务中的隔离级别行为:

CREATE PROCEDURE ReadCommittedIsolationLevel
AS
BEGIN
    BEGIN TRANSACTION t1
    BEGIN TRY
        EXEC SnapShotIsolationLevel
        COMMIT TRANSACTION
    END TRY
    BEGIN CATCH
        PRINT ERROR_MESSAGE()
        ROLLBACK TRANSACTION t1
    END CATCH
END

CREATE PROCEDURE SnapShotIsolationLevel
AS
BEGIN
    SET TRANSACTION ISOLATION LEVEL SNAPSHOT        
    BEGIN TRANSACTION t2
        BEGIN TRY
            SELECT TOP 20 * 
            FROM Orders 
            ORDER BY 1 DESC

            COMMIT
        END TRY
        BEGIN CATCH
            PRINT ERROR_MESSAGE()
            ROLLBACK TRAN t2
        END CATCH
END

然后我运行它:

EXEC ReadCommittedIsolationLevel

我收到此错误:

  

数据库中的交易失败' MyDataBase'因为该语句是在快照隔离下运行但事务未在快照隔离中启动。除非事务最初是在快照隔离级别下启动的,否则您无法在事务启动后将事务的隔离级别更改为快照   无法回滚t2。没有找到该名称的交易或保存点。

如果我删除事务并像普通存储过程一样运行它,它可以正常工作。

为什么?

1 个答案:

答案 0 :(得分:4)

错误给出了正确的解释:

  

您无法将事务的隔离级别更改为快照   交易开始后。

SQL Server没有nested transactions,唯一真正的事务是在Read Committed下启动的外部事务,下一个begin tran除了递增@@trancount之外什么都不做。您可以在此处详细了解:A SQL Server DBA myth a day: (26/30) nested transactions are real by Paul Randal

Snapshot Isolation表示transaction level处的一致数据,而非声明级别(RCSI),因此您应在交易开始时将Isolation level更改为Snapshot或你无法将它改为Snapshot