Shi*_*aru 9 transactions nested sql-server-2008
让我们说这是情况:
[Stored Proc 1]
BEGIN
BEGIN TRANSACTION
...
exec sp 2
COMMIT
END
Run Code Online (Sandbox Code Playgroud)
现在,如果SP 2 - 由于某种原因回滚,SP 1 - 提交或回滚还是抛出异常?
谢谢.
SQL Server中没有自治事务.您可能会看到@@TRANCOUNT增加超过1,但回滚会影响整个事情.
编辑要求指出文件.不知道明确记录这个主题的主题,但我可以在行动中向您展示.
USE tempdb;
GO
Run Code Online (Sandbox Code Playgroud)
内部过程:
CREATE PROCEDURE dbo.sp2
@trip BIT
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRANSACTION;
PRINT @@TRANCOUNT;
IF @trip = 1
BEGIN
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION;
END
ELSE
BEGIN
IF @@TRANCOUNT > 0
COMMIT TRANSACTION;
END
PRINT @@TRANCOUNT;
END
GO
Run Code Online (Sandbox Code Playgroud)
外部过程:
CREATE PROCEDURE dbo.sp1
@trip BIT
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRANSACTION;
PRINT @@TRANCOUNT;
BEGIN TRY
EXEC dbo.sp2 @trip = @trip;
END TRY
BEGIN CATCH
PRINT ERROR_MESSAGE();
END CATCH
PRINT @@TRANCOUNT;
IF @@TRANCOUNT > 0
COMMIT TRANSACTION;
PRINT @@TRANCOUNT;
END
GO
Run Code Online (Sandbox Code Playgroud)
所以现在让我们调用它,让一切都提交:
EXEC dbo.sp1 @trip = 0;
Run Code Online (Sandbox Code Playgroud)
结果:
1
2
1
1
0
现在让我们调用它并回滚内部过程:
EXEC dbo.sp1 @trip = 1;
Run Code Online (Sandbox Code Playgroud)
结果:
1
2
0 < - 请注意,此处的回滚
在EXECUTE表示BEGIN和COMMIT语句的数量不匹配后回滚两个 事务计数.先前的计数= 1,当前计数= 0
0
0
可以回滚SP2完成的工作,而不会松开SP1完成的工作.但要实现这一点,您必须使用非常特定的模式编写存储过程,如异常处理和嵌套事务中所述:
create procedure [usp_my_procedure_name]
as
begin
set nocount on;
declare @trancount int;
set @trancount = @@trancount;
begin try
if @trancount = 0
begin transaction
else
save transaction usp_my_procedure_name;
-- Do the actual work here
lbexit:
if @trancount = 0
commit;
end try
begin catch
declare @error int, @message varchar(4000), @xstate int;
select @error = ERROR_NUMBER(), @message = ERROR_MESSAGE(), @xstate = XACT_STATE();
if @xstate = -1
rollback;
if @xstate = 1 and @trancount = 0
rollback
if @xstate = 1 and @trancount > 0
rollback transaction usp_my_procedure_name;
raiserror ('usp_my_procedure_name: %d: %s', 16, 1, @error, @message) ;
end catch
end
Run Code Online (Sandbox Code Playgroud)
并非所有错误都是可恢复的,事务无法从中恢复多个错误条件,最明显的例子是死锁(在事务已经回滚后,会通知您死锁异常).必须使用此模式编写SP1和SP @.如果你有一个流氓SP,或者你想简单地利用现有的存储过程,ROLLBACK那么就会发出声明,那么你的原因就会丢失.