原生程序中不可部分完成的區塊
適用於:SQL Server Azure SQL 資料庫 Azure SQL 受控執行個體
BEGIN ATOMIC 是 ANSI SQL 標準的一部分。 SQL Server 支援原生編譯的預存程序最上層的 ATOMIC 區塊,以及原生編譯之純量使用者定義函數的 ATOMIC 區塊。 如需這些函數的詳細資訊,請參閱 記憶體內部 OLTP 的純量使用者定義函數。
每個原生編譯預存程序剛好包含一個 Transact-SQL 陳述式區塊。 這是 ATOMIC 區塊。
非原生、解譯的 Transact-SQL 預存程序和隨選批次不支援不可部分完成的區塊。
不可部分完成的區塊會在交易內執行 (以不可分割方式)。 區塊中的所有陳述式將會成功,或是整個區塊將會回復到區塊開頭所建立的儲存點。 此外,對於不可部分完成的區塊而言,工作階段設定是固定的。 在工作階段中以不同設定執行相同的不可部分完成的區塊將會產生相同的行為,與目前工作階段的設定無關。
交易和錯誤處理
如果交易已經存在於工作階段 (因為執行 BEGIN TRANSACTION 陳述式的批次和交易依然使用中),則啟動 ATOMIC 區塊將會在交易中建立儲存點。 如果區塊結束而沒有發生例外狀況,則會認可針對區塊建立的儲存點,但在工作階段層級的交易認可之前不會認可交易。 如果區塊擲回例外狀況,則會回復區塊的作用,但是工作階段層級的交易將會繼續,除非例外狀況讓交易毀滅。 例如,寫入衝突將會毀滅交易,但類型轉換錯誤則不會。
如果工作階段上沒有使用中交易, BEGIN ATOMIC 將會開始新的交易。 如果區塊範圍之外未擲回任何例外狀況,此交易將會在區塊結尾認可。 如果區塊擲回例外狀況 (也就是說,未在區塊內捕捉及處理例外狀況),交易將會回復。 如果交易橫跨單一 ATOMIC 區塊 (單一原生編譯的預存程序),您就不需要撰寫明確的 BEGIN TRANSACTION 和 COMMIT 或 ROLLBACK 陳述式。
原生編譯的預存程序支援 TRY、 CATCH 和 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 及 41839。
工作階段設定
當編譯預存程序時,將會修復不可部分完成的區塊內的工作階段設定。 某些設定可以使用 BEGIN ATOMIC 來指定,而其他設定則一律固定為相同的值。
BEGIN ATOMIC 需要以下選項:
必要設定 | 描述 |
---|---|
TRANSACTION ISOLATION LEVEL | 支援的值為 SNAPSHOT、REPEATABLEREAD 和 SERIALIZABLE。 |
LANGUAGE | 判斷日期和時間格式及系統訊息。 sys.syslanguages (Transact-SQL) 中的所有語言和別名都受到支援。 |
以下是選擇性設定:
選擇性設定 | 描述 |
---|---|
DATEFORMAT | 所有 SQL Server 日期格式都受支援。 當指定時,DATEFORMAT 會覆寫與 LANGUAGE 相關聯的預設日期格式。 |
DATEFIRST | 當指定時,DATEFIRST 會覆寫與 LANGUAGE 相關聯的預設值。 |
DELAYED_DURABILITY | 支援的值為 OFF 和 ON。 SQL Server 交易認可可能是完全持久、預設值或延遲的持久。如需詳細資訊,請參閱控制交易持久性。 |
對於所有原生編譯預存程序中所有不可部分完成的區塊,下列 SET 選項都有相同的系統預設值:
Set 選項 | 不可部分完成的區塊的系統預設值 |
---|---|
ANSI_NULLS | 開啟 |
ANSI_PADDING | 開啟 |
ANSI_WARNING | 開啟 |
ARITHABORT | 開啟 |
ARITHIGNORE | OFF |
CONCAT_NULL_YIELDS_NULL | 開啟 |
IDENTITY_INSERT | OFF |
NOCOUNT | 開啟 |
NUMERIC_ROUNDABORT | OFF |
QUOTED_IDENTIFIER | 開啟 |
ROWCOUNT | 0 |
TEXTSIZE | 0 |
XACT_ABORT | OFF 未捕捉到的例外狀況會造成不可部分完成的區塊回復,但是並不會造成交易中止,除非錯誤會毀滅交易。 |