BEGIN ATOMIC 是 ANSI SQL 标准的一部分。 SQL Server 仅支持本机编译存储过程的顶级原子块。
每个本机编译的存储过程仅包含一个 Transact-SQL 语句块。 这是 ATOMIC 块。
非本机解释的 Transact-SQL 存储过程和即席批处理不支持原子块。
原子块在事务中执行(原子方式)。 要么块中的所有语句都成功,要么整个块将回滚到在块开始时创建的保存点。 此外,原子块的会话设置已固定。 在具有不同设置的会话中执行相同的原子块将导致与当前会话的设置无关的相同行为。
事务和错误处理
如果会话上已存在事务(因为批处理执行 BEGIN TRANSACTION 了语句且事务保持活动状态),则启动原子块将在事务中创建保存点。 如果块在没有异常的情况下退出,那么为该块创建的保存点将提交,但事务只有在会话级别的事务提交时才会提交。 如果块引发异常,则会回滚该块的影响,但会话级别的事务将继续进行,除非异常导致事务失败。 例如,写入冲突会导致事务失败,而类型强制转换错误则不会。
如果会话中没有活动事务, BEGIN ATOMIC 将启动一个新事务。 如果未在块范围之外引发异常,则事务将在块的末尾提交。 如果块引发异常(也就是说,该异常未捕获并在块中处理),则事务将回滚。 对于跨单个原子块(单个本机编译存储过程)的事务,无需编写显式 BEGIN TRANSACTION 和 COMMIT 或 ROLLBACK 语句。
本机编译的存储过程支持TRYCATCH错误处理和THROW构造。 不支持 RAISERROR。
以下示例演示了使用原子块和本机编译的存储过程的错误处理行为:
-- sample table
CREATE TABLE dbo.t1 (
c1 int not null primary key nonclustered
)
WITH (MEMORY_OPTIMIZED=ON)
GO
-- sample proc that inserts 2 rows
CREATE PROCEDURE dbo.usp_t1 @v1 bigint not null, @v2 bigint not null
WITH NATIVE_COMPILATION, SCHEMABINDING, EXECUTE AS OWNER
AS
BEGIN ATOMIC
WITH (TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = N'us_english', DELAYED_DURABILITY = ON)
INSERT dbo.t1 VALUES (@v1)
INSERT dbo.t1 VALUES (@v2)
END
GO
-- insert two rows
EXEC dbo.usp_t1 1, 2
GO
-- verify we have no active transaction
SELECT @@TRANCOUNT
GO
-- verify the rows 1 and 2 were committed
SELECT c1 FROM dbo.t1
GO
-- execute proc with arithmetic overflow
EXEC dbo.usp_t1 3, 4444444444444
GO
-- expected error message:
-- Msg 8115, Level 16, State 0, Procedure usp_t1
-- Arithmetic overflow error converting bigint to data type int.
-- verify we have no active transaction
SELECT @@TRANCOUNT
GO
-- verify rows 3 was not committed; usp_t1 has been rolled back
SELECT c1 FROM dbo.t1
GO
-- start a new transaction
BEGIN TRANSACTION
-- insert rows 3 and 4
EXEC dbo.usp_t1 3, 4
-- verify there is still an active transaction
SELECT @@TRANCOUNT
-- verify the rows 3 and 4 were inserted
SELECT c1 FROM dbo.t1 WITH (SNAPSHOT)
ORDER BY c1
-- catch the arithmetic overflow error
BEGIN TRY
EXEC dbo.usp_t1 5, 4444444444444
END TRY
BEGIN CATCH
PRINT N'Error occurred: ' + error_message()
END CATCH
-- verify there is still an active transaction
SELECT @@TRANCOUNT
-- verify rows 3 and 4 are still in the table, and row 5 has not been inserted
SELECT c1 FROM dbo.t1 WITH (SNAPSHOT)
ORDER BY c1
COMMIT
GO
-- verify we have no active transaction
SELECT @@TRANCOUNT
GO
-- verify rows 3 and 4 has been committed
SELECT c1 FROM dbo.t1
ORDER BY c1
GO
以下特定于内存优化表的错误消息将导致事务失败。 如果在原子块的范围内发生,则会导致事务中止:10772、41301、41302、41305、41325、41332 和 41333。
会话设置
编译存储过程时,原子块中的会话设置将被固定。 某些设置可以通过 BEGIN ATOMIC 指定,而其他设置始终固定为相同的值。
以下选项必须与 BEGIN ATOMIC 一起使用:
| 必需的设置 | DESCRIPTION |
|---|---|
TRANSACTION ISOLATION LEVEL |
支持的值为 SNAPSHOT、 REPEATABLEREAD和 SERIALIZABLE。 |
LANGUAGE |
确定日期和时间格式和系统消息。 支持 sys.syslanguages(Transact-SQL)中的所有语言和别名。 |
以下设置是可选的:
| 可选设置 | DESCRIPTION |
|---|---|
DATEFORMAT |
支持所有 SQL Server 日期格式。 指定后,DATEFORMAT 覆盖与 LANGUAGE关联的默认日期格式。 |
DATEFIRST |
指定时,DATEFIRST 会覆盖与 LANGUAGE 关联的默认值。 |
DELAYED_DURABILITY |
支持的值是 OFF 和 ON。SQL Server 事务提交可以是完全持久、默认值或延迟持久。有关详细信息,请参阅 控制事务持续性。 |
以下 SET 选项对所有本机编译的存储过程中的所有原子块具有相同的系统默认值:
| 设置选项 | 原子块的系统默认值 |
|---|---|
| ANSI_NULLS | 开 |
| ANSI_PADDING | 开 |
| ANSI_WARNING | 开启 |
| ARITHABORT | 开 |
| ARITHIGNORE | 关闭 |
| CONCAT_NULL_YIELDS_NULL(空值连接结果为空值) | 开启 |
| IDENTITY_INSERT(插入身份列) | 关闭 |
| 无计数 | 开 |
| NUMERIC_ROUNDABORT | 关闭 |
| 引用标识符 | 打开 |
| 行数 | 0 |
| 文本大小 | 0 |
| XACT_ABORT | 关闭 未捕获的异常会导致原子操作块回滚,但不会导致事务中止,除非错误是导致事务失败的原因。 |