メモリ最適化テーブルにアクセスするトランザクションで発生するエラー条件があります。
-
- 現在のトランザクションは、トランザクションの開始後に更新されたレコードを更新しようとしました。
-
- 反復可能な読み取り検証エラーのため、現在のトランザクションのコミットに失敗しました。
-
- シリアル化可能な検証エラーのため、現在のトランザクションのコミットに失敗しました。
-
- 現在のトランザクションが依存関係を取得した以前のトランザクションが中止され、現在のトランザクションはコミットできなくなります。
これらのエラーの一般的な原因は、同時に実行されるトランザクション間の干渉です。 一般的な修正アクションは、トランザクションを再試行することです。
これらのエラー条件の詳細については、「Memory-Optimized テーブルのトランザクションでの競合の検出、検証、コミットの依存関係チェック」セクションを参照してください。
メモリ最適化テーブルでデッドロック (エラー コード 1205) を発生できません。 ロックは、メモリ最適化テーブルには使用されません。 ただし、アプリケーションにデッドロックの再試行ロジックが既に含まれている場合は、既存のロジックを拡張して新しいエラー コードを含めることができます。
再試行に関する考慮事項
アプリケーションでは通常、トランザクション間で競合が発生し、それらの競合を解決するために再試行ロジックを実装する必要があります。 発生した競合の数は、さまざまな要因によって異なります。
個別行に対する競合。 同じ行を更新しようとするトランザクションの数が増えると、競合の可能性が高くなります。
REPEATABLE READ トランザクションによって読み取られた行の数。 読み取られる行が多いほど、これらの行の一部が同時トランザクションによって更新される可能性が高くなります。 これにより、反復可能な読み取り検証エラーが発生します。
SERIALIZABLE トランザクションで使用されるスキャン範囲のサイズ。 スキャン範囲が大きいほど、同時実行トランザクションによってファントム行が導入され、シリアル化可能な検証エラーが発生する可能性が高くなります。
アプリケーションでこれらの競合を回避することは困難であり、再試行ロジックが必要です。
重要
メモリ最適化テーブルにアクセスする読み取り/書き込みトランザクションには、再試行ロジックが必要です。
Read-Only トランザクションとネイティブ コンパイル ストアド プロシージャに関する考慮事項
ネイティブ コンパイル ストアド プロシージャの 1 回の実行にまたがる読み取り専用トランザクションでは、REPEATABLE READ および SERIALIZABLE トランザクションの検証は必要ありません。 トランザクションが読み取り専用であるため、書き込み競合は発生できません。
ただし、依存関係エラーは引き続き発生する可能性があります。 依存関係のエラーは、競合の結果として発生するエラーよりもまれです。 そのため、多くの場合、ネイティブ コンパイル ストアド プロシージャの 1 回の実行にまたがる読み取り専用トランザクションでは、特定の再試行ロジックは必要ありません。
Read-Only トランザクションとコンテナー間トランザクションに関する考慮事項
読み取り専用のクロスコンテナー トランザクション (ネイティブ コンパイル ストアド プロシージャのコンテキスト外で開始されるトランザクション) は、メモリ最適化テーブルがすべて SNAPSHOT 分離の下でアクセスされている場合、検証を実行しません。 ただし、メモリ最適化テーブルが REPEATABLE READ または SERIALIZABLE 分離の下でアクセスされる場合、検証はコミット時に実行されます。 この場合、再試行ロジックが必要になる場合があります。
詳細については、「 トランザクション分離レベルのクロスコンテナー トランザクション」セクションを参照してください。
再試行ロジックの実装
メモリ最適化テーブルにアクセスするすべてのトランザクションと同様に、書き込み競合 (エラー コード 41302) や依存関係エラー (エラー コード 41301) など、潜在的なエラーを処理するための再試行ロジックを検討する必要があります。 ほとんどのアプリケーションではエラー率は低くなりますが、トランザクションを再試行してエラーを処理する必要があります。 再試行ロジックを実装するには、次の 2 つの方法が推奨されます。
クライアント側の再試行。 クライアント側の再試行は、一般的なケースで再試行ロジックを実装する場合に推奨される方法です。 クライアント アプリケーションは、トランザクションによってスローされたエラーをキャッチし、トランザクションを再試行します。 既存のクライアント アプリケーションにデッドロックを処理するための再試行ロジックがある場合は、アプリケーションを拡張して新しいエラー コードを処理できます。
ラッパー ストアド プロシージャを使用すること。 クライアントは、ネイティブ コンパイル ストアド プロシージャを呼び出すか、トランザクションを実行する、解釈された Transact-SQL ストアド プロシージャを呼び出します。 ラッパー プロシージャは、try/catch ロジックを使用してエラーをキャッチし、必要に応じてプロシージャ呼び出しを再試行します。 エラーが発生する前に結果がクライアントに返され、クライアントが破棄を認識しない可能性があります。 そのため、このメソッドは、クライアントに結果セットを返さないネイティブ コンパイル ストアド プロシージャでのみ使用することをお勧めします。
再試行ロジックは、Transact-SQL または中間層のアプリケーション コードで実装できます。
再試行ロジックを考慮する理由として、次の 2 つがあります。
クライアント アプリケーションには、拡張できる他のエラー コード (1205 など) の再試行ロジックがあります。
競合はまれであり、準備された実行を使用してエンドツーエンドの待機時間を短縮することが重要です。 ネイティブ コンパイル ストアド プロシージャを直接実行する方法の詳細については、「 ネイティブ コンパイル ストアド プロシージャ」を参照してください。
次の例は、ネイティブ コンパイル ストアド プロシージャまたはクロスコンテナー トランザクションの呼び出しを含む、解釈された Transact-SQL ストアド プロシージャの再試行ロジックを示しています。
CREATE PROCEDURE usp_my_procedure @param1 type1, @param2 type2, ...
AS
BEGIN
-- number of retries - tune based on the workload
DECLARE @retry INT = 10
WHILE (@retry > 0)
BEGIN
BEGIN TRY
-- exec usp_my_native_proc @param1, @param2, ...
-- or
-- BEGIN TRANSACTION
-- ...
-- COMMIT TRANSACTION
SET @retry = 0
END TRY
BEGIN CATCH
SET @retry -= 1
-- the error number for deadlocks (1205) does not need to be included for
-- transactions that do not access disk-based tables
IF (@retry > 0 AND error_number() in (41302, 41305, 41325, 41301, 1205))
BEGIN
-- these error conditions are transaction dooming - rollback the transaction
-- this is not needed if the transaction spans a single native proc execution
-- as the native proc will simply rollback when an error is thrown
IF XACT_STATE() = -1
ROLLBACK TRANSACTION
-- use a delay if there is a high rate of write conflicts (41302)
-- length of delay should depend on the typical duration of conflicting transactions
-- WAITFOR DELAY '00:00:00.001'
END
ELSE
BEGIN
-- insert custom error handling for other error conditions here
-- throw if this is not a qualifying error condition
;THROW
END
END CATCH
END
END
こちらもご覧ください
Memory-Optimized テーブルのトランザクションについて
Memory-Optimized テーブル内のトランザクション
Memory-Optimized テーブルでのトランザクション分離レベルのガイドライン