この記事には、SQL プールでのトランザクションの実装とソリューションの開発に関するヒントが含まれています。
予期される事柄
ご期待のとおり、SQL プールはデータ ウェアハウス ワークロードの一部としてトランザクションをサポートします。 ただし、SQL プールが大規模に維持されるようにするために、SQL Server と比較すると一部の機能が制限されます。 この記事では、相違点について説明します。
トランザクション分離レベル
SQL プールは ACID トランザクションを実装します。 トランザクション サポートの分離レベルは、既定では READ UNCOMMITTED です。 これは READ COMMITTED SNAPSHOT ISOLATION に変更できます。それには、マスター データベースに接続する際にユーザー SQL プールの READ_COMMITTED_SNAPSHOT データベース オプションをオンにします。
有効にすると、このデータベース内のすべてのトランザクションが READ COMMITTED SNAPSHOT ISOLATION で実行され、セッション レベルで READ UNCOMMITTED を設定することはできません。 詳細については、 ALTER DATABASE SET オプション (Transact-SQL) を参照してください。
トランザクション サイズ
1 つのデータ変更トランザクションのサイズが制限されます。 この制限はディストリビューションごとに適用されます。 したがって、割り当ての合計は、制限に分布数を掛けることによって計算できます。
トランザクション内の行の最大数を概算するには、ディストリビューションの上限を各行の合計サイズで割ります。 可変長列の場合は、最大サイズを使用するのではなく、平均列長を使用することを検討してください。
次の表では、次の 2 つの前提条件が行われています。
- データの均等な分散が発生しました
- 平均行長は 250 バイトです
Gen2
| DWU | ディストリビューションあたりの上限 (GB) | 分布の数 | 最大トランザクション サイズ (GB) | # ディストリビューションあたりの行数 | トランザクションあたりの最大行数 |
|---|---|---|---|---|---|
| DW100c | 1 | 60 | 60 | 4,000,000 | 240,000,000 |
| DW200c | 1.5 | 60 | 90 | 6,000,000 | 3億6千万 |
| 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 | 6,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 |
第1世代
| DWU | ディストリビューションあたりの上限 (GB) | 分布の数 | 最大トランザクション サイズ (GB) | # ディストリビューションあたりの行数 | トランザクションあたりの最大行数 |
|---|---|---|---|---|---|
| DW100 | 1 | 60 | 60 | 4,000,000 | 240,000,000 |
| DW200 | 1.5 | 60 | 90 | 6,000,000 | 3億6千万 |
| 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 | 6,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 |
トランザクション サイズの制限は、トランザクションまたは操作ごとに適用されます。 すべての同時実行トランザクションに適用されるわけではありません。 そのため、各トランザクションでは、この量のデータをログに書き込むのが許可されます。
ログに書き込まれるデータの量を最適化して最小限に抑えるには、 トランザクションのベスト プラクティス に関する記事を参照してください。
Warnung
最大トランザクション サイズは、データの分散が均等である 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;
上記のコードでは、次のエラー メッセージが表示されます。
メッセージ 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 ブロック内のエラー情報を読み取る前にトランザクションの ROLLBACK が行われなければならなかったということです。
Error_Line() 関数
また、SQL プールで ERROR_LINE() 関数が実装またはサポートされていないことにも注目してください。 コードにこれが含まれる場合は、SQL プールに準拠するために削除する必要があります。
代わりにコードでクエリ ラベルを使用して、同等の機能を実装します。 詳細については、 LABEL の記事を参照してください。
THROW と RAISERROR の使用
THROW は、SQL プールで例外を発生させるためのより最新の実装ですが、RAISERROR もサポートされています。 ただし、注意する価値がある違いがいくつかあります。
- ユーザー定義のエラー メッセージ番号は、THROW の 100,000 ~ 150,000 の範囲にすることはできません
- RAISERROR エラー メッセージが 50,000 で修正されました
- sys.messages の使用はサポートされていません
制限事項
SQL プールには、トランザクションに関連するその他のいくつかの制限があります。
これらは次のとおりです。
- 分散トランザクションなし
- 入れ子になったトランザクションは許可されていません
- 保存ポイントは許可されていません
- 名前付きトランザクションなし
- マークされたトランザクションがありません
- ユーザー定義トランザクション内での CREATE TABLE などの DDL のサポートなし
次のステップ
トランザクションの最適化の詳細については、「 トランザクションのベスト プラクティス」を参照してください。 その他の SQL プールのベスト プラクティスについては、 SQL プールのベスト プラクティスに関するページを参照してください。