在 Azure Synapse Analytics 中使用專用 SQL 池來管理交易

在 Azure Synapse Analytics 中實作專用 SQL 池交易以開發解決方案的技巧。

預期內容

如你所料,專用 SQL 池支援資料倉儲工作負載中的交易。 然而,為了確保專用 SQL 池的效能能在大規模範圍內維持,與 SQL Server 相比,有些功能受到限制。 本文強調了這些差異並列出其他差異。

交易隔離層級

專用 SQL 池實作 ACID 交易。 交易支援的隔離層預設為 READ UNCOMMITTED。 您可在連線至 master 資料庫時,開啟使用者資料庫的 [READ_COMMITTED_SNAPSHOT] 資料庫選項,將其變更為 [READ COMMITTED SNAPSHOT ISOLATION]。

啟用後,此資料庫中所有交易都會在 READ COMMITTED SNAPSHOT ISOLATION 的狀態下執行,且將不會接受在工作階段層級上設定為 READ UNCOMMITTED。 詳情請查閱 ALTER DATABASE SET 選項(Transact-SQL )。

交易規模

單一資料修改交易的大小有限。 該限額是依分配適用。 因此,總分配可透過將極限乘以分布計數來計算。

為了近似交易中最大列數,將分配上限除以每列的總大小。 對於可變長度的欄位,建議採用平均欄位長度,而非使用最大大小。

下表中提出以下假設:

  • 數據分布均等
  • 平均列長度為 250 位元組

Gen2

DWU 每個分發的上限 (GB) 發行版數量 最大交易大小(GB) 每個分發的列數 每筆交易的最大列數
DW100c 1 60 60 4,000,000 240,000,000
DW200c 1.5 60 90 6,000,000 360,000,000
DW300c 2.25 60 135 9,000,000 540,000,000
DW400c 3 60 180 12,000,000 720,000,000
DW500c 3.75 60 225 15,000,000 900,000,000
DW1000c 7.5 60 450 30,000,000 1,800,000,000
DW1500c 11.25 60 675 45,000,000 2,700,000,000
DW2000c 15 60 900 60,000,000(六千萬) 3,600,000,000
DW2500c 18.75 60 1125 75,000,000 4,500,000,000
DW3000c 22.5 60 1,350 90,000,000 5,400,000,000
DW5000c 37.5 60 2,250 150,000,000 9,000,000,000
DW6000c 45 60 2,700 180,000,000 10,800,000,000
DW7500c 56.25 60 3,375 225,000,000 13,500,000,000
DW10000c 75 60 4,500 300,000,000 18,000,000,000
DW15000c 112.5 60 6,750 450,000,000 27,000,000,000
DW30000c 225 60 13,500 900,000,000 54,000,000,000

第一代

DWU 每個分發的上限 (GB) 發行版數量 最大交易大小(GB) 每個分發的列數 每筆交易的最大列數
DW100 1 60 60 4,000,000 240,000,000
DW200 1.5 60 90 6,000,000 360,000,000
DW300 2.25 60 135 9,000,000 540,000,000
DW400 3 60 180 12,000,000 720,000,000
DW500 3.75 60 225 15,000,000 900,000,000
DW600 4.5 60 270 18,000,000 1,080,000,000
DW1000 7.5 60 450 30,000,000 1,800,000,000
DW1200 9 60 540 36,000,000 2,160,000,000
DW1500 11.25 60 675 45,000,000 2,700,000,000
DW2000 15 60 900 60,000,000(六千萬) 3,600,000,000
DW3000 22.5 60 1,350 90,000,000 5,400,000,000
DW6000 45 60 2,700 180,000,000 10,800,000,000

交易大小限制是依交易或操作套用。 此規定並非適用於所有同時進行的交易。 因此,每個交易都被允許將此量的資料寫入日誌。

為了優化並減少寫入日誌的資料量,請參考 《交易》最佳實務 條目。

警告

最大交易大小只能在資料分布均勻的 HASH 或ROUND_ROBIN分散式資料表中達成。 如果交易以偏斜方式寫入資料給分布,那麼極限很可能在交易最大大小之前就已達到。

交易狀態

專用 SQL 池使用 XACT_STATE() 函式來以 -2 值回報失敗的交易。 此值表示交易已失敗,並僅標記用於回滾。

備註

XACT_STATE函式使用 -2 來表示交易失敗,這與 SQL Server 的行為有所不同。 SQL Server 使用值 -1 來表示不可提交的交易。 SQL Server 可以容忍交易內部的某些錯誤,無需標記為不可提交。 例如,SELECT 1/0可能會引發錯誤,但不會強迫交易進入無法提交的狀態。 SQL Server 也允許在未提交的交易中進行讀取。 然而,專用 SQL 池不允許你這麼做。 如果專用 SQL 集區交易中發生錯誤,系統會自動進入 -2 狀態,且在該陳述式回滾之前,您將無法再執行任何 SELECT 陳述式。 因此,檢查你的應用程式代碼是否使用 XACT_STATE() 非常重要,因為你可能需要修改程式碼。

例如,在 SQL Server 中,你可能會看到一個交易看起來像這樣:

SET NOCOUNT ON;
DECLARE @xact_state smallint = 0;

BEGIN TRAN
    BEGIN TRY
        DECLARE @i INT;
        SET     @i = CONVERT(INT,'ABC');
    END TRY
    BEGIN CATCH
        SET @xact_state = XACT_STATE();

        SELECT  ERROR_NUMBER()    AS ErrNumber
        ,       ERROR_SEVERITY()  AS ErrSeverity
        ,       ERROR_STATE()     AS ErrState
        ,       ERROR_PROCEDURE() AS ErrProcedure
        ,       ERROR_MESSAGE()   AS ErrMessage
        ;

        IF @@TRANCOUNT > 0
        BEGIN
            ROLLBACK TRAN;
            PRINT 'ROLLBACK';
        END

    END CATCH;

IF @@TRANCOUNT >0
BEGIN
    PRINT 'COMMIT';
    COMMIT TRAN;
END

SELECT @xact_state AS TransactionState;

前述代碼會給出以下錯誤訊息:

Msg 111233、16 層,狀態 1、1 號線 111233;目前的交易已中止,所有待處理的變更都已回滾。 原因:處於僅限回滾狀態的交易在 DDL、DML 或 SELECT 陳述句執行之前,未明確回滾。

你不會得到 ERROR_* 函數的輸出。

在專用 SQL 池中,程式碼需要稍作修改:

SET NOCOUNT ON;
DECLARE @xact_state smallint = 0;

BEGIN TRAN
    BEGIN TRY
        DECLARE @i INT;
        SET     @i = CONVERT(INT,'ABC');
    END TRY
    BEGIN CATCH
        SET @xact_state = XACT_STATE();

        IF @@TRANCOUNT > 0
        BEGIN
            ROLLBACK TRAN;
            PRINT 'ROLLBACK';
        END

        SELECT  ERROR_NUMBER()    AS ErrNumber
        ,       ERROR_SEVERITY()  AS ErrSeverity
        ,       ERROR_STATE()     AS ErrState
        ,       ERROR_PROCEDURE() AS ErrProcedure
        ,       ERROR_MESSAGE()   AS ErrMessage
        ;
    END CATCH;

IF @@TRANCOUNT >0
BEGIN
    PRINT 'COMMIT';
    COMMIT TRAN;
END

SELECT @xact_state AS TransactionState;

預期行為現在被觀察到。 交易中的錯誤會被管理,ERROR_* 函式會如預期提供值。

唯一改變的是,交易的回滾必須在讀取 CATCH 區塊的錯誤資訊之前完成。

Error_Line() 函數

同時值得注意的是,專用 SQL 池並未實作或支援 ERROR_LINE() 函式。 如果你的程式碼中有這個函式,你需要移除它,才能符合專用的 SQL 池要求。 改用程式碼中的查詢標籤來實作等效功能。 欲了解更多資訊,請參閱 LABEL 文章。

THROW與RAISERROR的使用

THROW 是在專用 SQL 資料庫中提出例外的較現代化實作,但同時也支援 RAISERROR。 不過,還是有一些差異值得注意。

  • 使用者自訂的錯誤訊息數字不能在 THROW 的 100,000 到 150,000 之間
  • RAISERROR 錯誤訊息固定在 50,000
  • 不支援 sys.messages 的使用

局限性

專用 SQL 池在交易方面還有一些其他限制。 如下所示:

  • 沒有分散式交易
  • 不允許巢狀交易
  • 不允許儲存點
  • 無特定名稱的交易
  • 沒有標記交易
  • 在使用者定義的交易中,不支援 DDL,例如 CREATE TABLE。

下一步

欲了解更多交易優化,請參閱 交易最佳實務。 另外也提供 專用 SQL 池無伺服器 SQL 池的最佳實務指南。