SET XACT_ABORT ON
changes the behavior of statement-terminating errors so that they instead become batch-aborting errors. The batch within which your procedure is executing would be more likely to stop completely when an error was encountered, rather than continuing on to the next T-SQL statement.
This has implications for error-handling. Statement-terminating errors which would normally allow you to continue and execute handling code via a IF @@ERROR <> 0
block within your procedure will not be executed. What's worse, there is no way you can intercept batch-abortion in T-SQL code, so unless there is a check on @@ERROR
immediately in a following batch on the same connection, you might not know there was a problem.
Perhaps your INSERT
is failing quietly in some way that still allows the IDENTITY
seed to be incremented. This is not uncommon...identity values reside in the SQL Server memory cache, the volatility of which provides no guarantee that those values be continuous and without gaps.
Alternatively, the calling context of the stored procedure matters. If called from within an outer-scope transaction, either initiated by SQL Server or at the application level, then a rollback at that outer scope will rollback the inner scope work, regardless of explicit transaction handling code at the inner scope. Again, the IDENTITY
seed would be incremented.
TRY/CATCH
blocks (available since SQL Server 2005) obviate the need for SET XACT_ABORT ON
.