问题摘要:
我做了错误处理,看起来似乎太复杂了,仍然不能解决所有情况(因为在某些情况下,事务处于不可提交状态)。我怀疑我:
您能否提供更好的解决方案(针对下面描述的情况)?
关于我的情况:
我在SQL Server中有(一对)存储过程,这是从不同的地方调用的。可以概括为两种情况:
我做到了,该过程返回结果(1表示成功,0表示失败)+在出现错误的情况下返回消息以进行记录。
程序内部:
代码如下:
Create Procedure dbo.usp_MyProcedure
(
-- params here ...
@ReturnCode int out, -- 1 Success, != 1 Error
@ReturnMsg nvarchar(2048) out
)
AS
Begin
Set NoCount ON;
Set XACT_ABORT ON;
Declare @PartOfTran bit = 0;
IF(@@TRANCOUNT > 0)
Begin
SET @PartOfTran = 1;
SAVE TRAN MyTran;
END
Else
BEGIN TRAN MyTran;
Begin Try
-- insert table1
-- update table2
-- ....
IF(@PartOfTran = 0)
COMMIT TRAN MyTran;
Select @ReturnCode = 1, @ReturnMsg = Null;
End Try
Begin Catch
IF (XACT_STATE() = 1 And @PartOfTran = 1) OR @PartOfTran = 0
Rollback Tran MyTran;
Select @ReturnCode = 0, @ReturnMsg = ERROR_MESSAGE();
End Catch
End
其他文学:
从我最喜欢的博客中看到:
最佳答案
在任何情况下,您将无法实现仅回退usp_MyProcedure
中完成的工作的解决方案。考虑最明显的例子:死锁。当您收到关于异常1205的通知(您被选为死锁受害者)时,事务已经回滚(以允许进度)。随着错误处理的进行,唯一安全的选择是进一步引发并重新抛出,以便调用者有机会使用react。 “不可提交的事务”只是该主题的一种变体:当调用者开始事务时,错误处理无法以对调用者敏感的方式从这种情况中恢复。最好的事情是提高(重新 throw )。这就是为什么我使用您在Exception HAndling and Nested Transactions博客中看到的模式的原因
在Service Broker上下文中考虑这一点,意味着没有完全的项目符号证明,异常安全的消息处理例程。如果您遇到了不可提交的事务(或者在处理catch块时已经回滚的事务,例如1205死锁),那么您将不得不回滚整批收到的消息。在这种情况下,通常在最外面的catch块之后进行记录(通常在激活的过程中定位)。这是如何工作的伪代码:
usp_myActivatedProc
as
@commited = false;
@received = 0;
@errors = 0;
begin transaction
begin try
receive ... into @table;
@received = @@row_count;
foreach message in @table
save transaction
begin try
process one message: exec usp_myProcedure @msg
end try
begin catch
if xact_state()=1
rollback to savepoint
@errors += 1;
-- decide what to do with failed message, log
-- this failure may still be committed (receive won't roll back yet)
else
-- this is a lost cause, re-throw
raiserror
end catch
fetch next @table
endfor
commit
@commited = true;
end try
catch
@error_message = error_message();
if xact_state() != 0
rollback
end catch
if @commited = false
begin
insert into logging 'failed', @received, @error_message
end
关于sql-server-2008 - SQL过程中的错误处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9565250/