【问题标题】:Does SET XACT_ABORT ON do anything in a stored procedure if you're NOT in a transaction?如果您不在事务中,SET XACT_ABORT ON 是否会在存储过程中执行任何操作?
【发布时间】:2013-08-08 09:23:44
【问题描述】:

如果您不在事务中,SET XACT_ABORT ON 是否会在存储过程中执行任何操作?

我问我的存储过程似乎以某种方式回滚插入语句,即使失败的存储过程部分不在事务中。表的标识被向上推,但在存储过程返回后插入的行不存在,尽管插入是无条件的并且不在事务内。

或者还有什么其他原因导致 SQL Server 在事务之外回滚插入?

【问题讨论】:

  • 所有插入都在一个事务中。如果您不在显式事务中运行它,SQL Server 将为该语句启动一个新的。
  • 但是如果插入成功完成,有什么机制可以让它回滚呢?

标签: sql sql-server tsql stored-procedures transactions


【解决方案1】:

SET XACT_ABORT ON 改变语句终止错误的行为,使它们变成批处理中止错误。当遇到错误时,执行过程的批处理更有可能完全停止,而不是继续执行下一个 T-SQL 语句。

这对错误处理有影响。通常允许您通过过程中的IF @@ERROR <> 0 块继续并执行处理代码的语句终止错误将不会被执行。更糟糕的是,您无法拦截 T-SQL 代码中的批处理中止,因此除非在同一连接的下一个批处理中立即检查 @@ERROR,否则您可能不知道存在问题。

也许您的INSERT 以某种方式悄然失败,但仍允许增加IDENTITYseed。这并不少见...标识值驻留在 SQL Server 内存缓存中,其波动性不能保证这些值是连续的且没有间隙。

另外,存储过程的调用上下文也很重要。如果从外部范围事务中调用(由 SQL Server 或在应用程序级别启动),则在该外部范围的回滚将回滚内部范围的工作,而不管内部范围的显式事务处理代码如何。同样,IDENTITY 种子将增加。

TRY/CATCH 块(自 SQL Server 2005 起可用)消除了对 SET XACT_ABORT ON 的需求。

【讨论】:

  • 抱歉恢复了,但是我对带有TRY/CATCH 块的SP 有疑问,这似乎可以通过添加SET XACT_ABORT ON 来解决,而不是在每个CATCH 中使用IF XACT_STATE() ROLLBACK堵塞。你觉得这种方法有什么问题吗?在我的情况下,CATCH 块返回错误信息,但是当 TRY 块中的插入语句失败时,我收到 266 错误,CATCH 没有机会返回有用的错误信息。这似乎都源于围绕INSERT 语句的隐式事务。感谢您提供任何信息。
  • @DaveGoldsmith SET XACT_ABORT ON 掩盖了核心事务问题,但 MSFT 支持此 T-SQL 语言功能,因此您可以使用它。或许您的问题对Database Administrators 来说是个好问题?
猜你喜欢
  • 2015-12-19
  • 1970-01-01
  • 1970-01-01
  • 2010-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多