如果存在回滚,为什么这些嵌套的 SQL 服务器事务会抛出不匹配错误?
Why are these nested SQL Server transactions throwing a mismatch error if there is a rollback?
运行 'Test Errors' 我得到了意想不到的结果。我认为通过检查 @@Trancount
可以避免不匹配。任何人都可以帮助我更好地回滚错误吗?我想回滚所有嵌套的事务。存储过程既可以嵌套也可以独立。
alter procedure TestErrors
as
begin
begin try
begin transaction
exec TestErrorsInner;
IF @@TRANCOUNT > 0
commit transaction;
end try
begin catch
IF @@TRANCOUNT > 0
rollback transaction;
select ERROR_MESSAGE();
end catch
end
alter procedure TestErrorsInner
as
begin
begin try
begin transaction
RAISERROR('Test Error',16,1);
IF @@TRANCOUNT > 0
commit transaction;
end try
begin catch
IF @@TRANCOUNT > 0
rollback transaction;
select ERROR_MESSAGE();
end catch
end
结果:
Test Error
Transaction count after EXECUTE indicates a mismatching number of
BEGIN and COMMIT statements. Previous count = 1, current count = 0.
这是因为您在 TestErrors 中捕获了一个未处于活动状态的事务。
您已经在 TestErrorsInner
的 Catch
个区块中回滚了您的交易。
然后你又试图在TestErrors
中做COMMIT/ROLLBACK。所以它抛出一个错误。
您有责任在 TestErrorsInner
的 Catch
块中再次明确提出错误。因此该错误将成为父 SP 的输入。
所以你的 TestErrorsInner
应该像
ALTER PROCEDURE TESTERRORSINNER
AS
BEGIN
BEGIN TRY
BEGIN TRANSACTION
RAISERROR('TEST ERROR',16,1);
IF @@TRANCOUNT > 0
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION;
--SELECT ERROR_MESSAGE();
RAISERROR('TEST ERROR in Catch',16,1); --Here Raised
END CATCH
END
现在执行TestErrors
存储过程,你不会得到那个错误。
并且您可以使用XACT_STATE()
查看交易状态
调用 XACT_STATE()
将给出 0 或 1 或 -1 的结果(来自 MSDN)
- 如果为 1,事务是可提交的。
- 如果为 -1,事务不可提交,应该回滚。
- if XACT_STATE = 0 表示没有事务,提交或回滚操作会产生错误。
运行 'Test Errors' 我得到了意想不到的结果。我认为通过检查 @@Trancount
可以避免不匹配。任何人都可以帮助我更好地回滚错误吗?我想回滚所有嵌套的事务。存储过程既可以嵌套也可以独立。
alter procedure TestErrors
as
begin
begin try
begin transaction
exec TestErrorsInner;
IF @@TRANCOUNT > 0
commit transaction;
end try
begin catch
IF @@TRANCOUNT > 0
rollback transaction;
select ERROR_MESSAGE();
end catch
end
alter procedure TestErrorsInner
as
begin
begin try
begin transaction
RAISERROR('Test Error',16,1);
IF @@TRANCOUNT > 0
commit transaction;
end try
begin catch
IF @@TRANCOUNT > 0
rollback transaction;
select ERROR_MESSAGE();
end catch
end
结果:
Test Error
Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements. Previous count = 1, current count = 0.
这是因为您在 TestErrors 中捕获了一个未处于活动状态的事务。
您已经在 TestErrorsInner
的 Catch
个区块中回滚了您的交易。
然后你又试图在TestErrors
中做COMMIT/ROLLBACK。所以它抛出一个错误。
您有责任在 TestErrorsInner
的 Catch
块中再次明确提出错误。因此该错误将成为父 SP 的输入。
所以你的 TestErrorsInner
应该像
ALTER PROCEDURE TESTERRORSINNER
AS
BEGIN
BEGIN TRY
BEGIN TRANSACTION
RAISERROR('TEST ERROR',16,1);
IF @@TRANCOUNT > 0
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION;
--SELECT ERROR_MESSAGE();
RAISERROR('TEST ERROR in Catch',16,1); --Here Raised
END CATCH
END
现在执行TestErrors
存储过程,你不会得到那个错误。
并且您可以使用XACT_STATE()
调用 XACT_STATE()
将给出 0 或 1 或 -1 的结果(来自 MSDN)
- 如果为 1,事务是可提交的。
- 如果为 -1,事务不可提交,应该回滚。
- if XACT_STATE = 0 表示没有事务,提交或回滚操作会产生错误。