Sky*_*Sky 9 sql-server sql-server-2008-r2 transaction jobs
我们在 SQL Server 作业的每个步骤中都有 DML 操作。为确保更新/插入在出现问题时回滚,我将每个步骤的数据修改包装在TRY CATCH
和TRANSACTION
块中:
BEGIN TRY
BEGIN TRANSACTION
[[INSERT/update statements]] ...
IF @@TRANCOUNT > 0
BEGIN
COMMIT TRANSACTION
PRINT 'Successful.'
END
END TRY
BEGIN CATCH
SELECT
ERROR_NUMBER() AS ErrorNumber,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_STATE() AS ErrorState,
ERROR_PROCEDURE() AS ErrorProcedure,
ERROR_LINE() AS ErrorLine,
ERROR_MESSAGE() AS ErrorMessage
IF @@TRANCOUNT > 0
BEGIN
ROLLBACK TRANSACTION
PRINT 'Unsuccessful.'
END
END CATCH
Run Code Online (Sandbox Code Playgroud)
它是否确保在出现错误时回滚数据操作?还是应该考虑其他因素?
有没有更好的方法来做到这一点(使用配置等)?
谢谢你。
我宁愿推荐一种类似于Exception Handling 和 Nested Transactions 的模式:
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)
此模式检查XACT_STATE()
catch 块中的 以防止不可提交的事务:
不可提交的事务和 XACT_STATE
如果在 TRY 块中产生的错误导致当前交易的状态无效,则该交易被归类为不可提交的交易。当错误发生在 TRY 块内时,通常会在 TRY 块外结束事务的错误会导致事务进入不可提交状态。不可提交的事务只能执行读操作或 ROLLBACK TRANSACTION。事务不能执行任何会生成写操作或 COMMIT TRANSACTION 的 Transact-SQL 语句。如果事务已被归类为不可提交事务,则 XACT_STATE 函数返回值 -1。批处理完成后,数据库引擎会回滚所有活动的不可提交事务。如果事务进入不可提交状态时没有发送错误消息,批处理完成后,将向客户端应用程序发送一条错误消息。这表明检测到一个不可提交的事务并回滚。
您的代码正在检查@@TRANCOUNT
它不能为 0 的地方,它使用信息 PRINT 消息和 SELECT 结果集的混合来通信成功,它不处理可恢复的错误。理想情况下,异常应该传播到客户端,在这种情况下传播到代理作业(即您的捕获应该重新引发)。
归档时间: |
|
查看次数: |
13853 次 |
最近记录: |