本机存储过程中的原子块

适用于:SQL ServerAzure SQL 数据库Azure SQL 托管实例

BEGIN ATOMIC 属于 ANSI SQL 标准。 SQL Server 支持在本机编译存储过程的顶层使用原子块,也支持本机编译的标量用户定义函数。 有关这些函数的详细信息,请参阅 内存中 OLTP 的标量用户定义函数

  • 每个本机编译的存储过程都恰好包含一个 Transact-SQL 语句块。 这是一个 ATOMIC 块。

  • 非本机解释型 Transact-SQL 存储过程和即席批处理不支持原子块。

原子块在事务内部(原子地)执行。 要么块中的所有语句都成功执行,要么整个块将回滚到该块开始时创建的保存点。 此外,会话设置在原子块内是固定的。 在具有不同设置的会话中执行相同的原子块,其行为将保持一致,不受当前会话设置的影响。

事务和错误处理

如果会话中已存在某个事务(因为某个批处理执行了 BEGIN TRANSACTION 语句,且该事务仍处于活动状态),则启动原子块将在该事务中创建一个保存点。 如果块在未抛出异常的情况下退出,则为该块创建的保存点将提交,但事务不会提交,直到会话级别的事务提交为止。 如果该代码块抛出异常,则该代码块产生的影响会被回滚,但会话级事务将继续进行,除非该异常会导致事务终止。 例如,写冲突会导致事务失败,但类型转换错误不会。

如果在会话上没有处于活动状态的事务,则 BEGIN ATOMIC 将开始一个新事务。 如果在块作用域外未抛出异常,事务将在块结束时提交。 如果代码块抛出异常(也就是说,如果未在代码块内捕获并处理该异常),则该事务会回滚。 对于跨单个原子块的事务(单个本机编译的存储过程),你无需编写显式的 BEGIN TRANSACTIONCOMMITROLLBACK 语句。

本机编译的存储过程支持使用 TRYCATCHTHROW 构造进行错误处理。 不支持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 和 41839。

会话设置

在编译存储过程时原子块中的会话设置是固定的。 某些设置可使用 BEGIN ATOMIC 指定,而其他设置则始终固定为相同值。

以下选项对于 BEGIN ATOMIC而言是必需的:

必需的设置 说明
TRANSACTION ISOLATION LEVEL 支持的值为 SNAPSHOTREPEATABLEREADSERIALIZABLE
LANGUAGE 确定日期和时间格式以及系统消息。 支持 sys.syslanguages (Transact-SQL) 中的所有语言和别名。

以下设置是可选的:

可选设置 说明
DATEFORMAT 支持所有 SQL Server 日期格式。 指定后,DATEFORMAT 会覆盖与 LANGUAGE 关联的默认日期格式。
DATEFIRST 指定后,DATEFIRST 将覆盖与 LANGUAGE 关联的默认值。
延迟耐久性 支持的值为 OFFON

SQL Server 事务提交可以是完全持久(默认),也可以是延迟持久。有关详细信息,请参阅《控制事务持久性》

以下 SET 选项对所有本机编译存储过程中的所有原子块具有相同的系统默认值:

设置选项 原子块的系统默认值
ANSI_NULLS
ANSI_PADDING
ANSI_WARNING
ARITHABORT
ARITHIGNORE
CONCAT_NULL_YIELDS_NULL
IDENTITY_INSERT
NOCOUNT
NUMERIC_ROUNDABORT
QUOTED_IDENTIFIER
ROWCOUNT 0
TEXTSIZE 0
XACT_ABORT

未捕获的异常会使原子块回滚,但不会导致事务中止,除非该错误会导致事务终止。

另请参阅

本机编译的存储过程