我创建了以下存储过程,以便检查事务中的隔离级别行为:
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。没有找到该名称的交易或保存点。
如果我删除事务并像普通存储过程一样运行它,它可以正常工作。
为什么?
答案 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
。