メモリ最適化テーブルでのトランザクションTransactions with Memory-Optimized Tables

適用対象: ○SQL Server ○Azure SQL Database XAzure SQL Data Warehouse XParallel Data WarehouseAPPLIES TO: yesSQL Server yesAzure SQL Database noAzure SQL Data Warehouse noParallel Data Warehouse

ここでは、メモリ最適化テーブルおよびネイティブ コンパイル ストアド プロシージャに固有のトランザクションをあらゆる側面から説明します。This article describes all the aspects of transactions that are specific to memory-optimized tables and natively compiled stored procedures.

SQL Server のトランザクション分離レベルは、ディスク ベースのテーブルとは異なる方法でメモリ最適化テーブルに適用されます。基になるメカニズムも異なっています。The transaction isolation levels in SQL Server apply differently to memory-optimized tables versus disk-based tables, and the underlying mechanisms are different. プログラマは、この違いを理解することで、高スループットのシステムを設計しやすくなります。An understanding of the differences helps the programmer design a high throughput system. トランザクションの整合性という目標は、すべての状況で共有されます。The goal of transaction integrity is shared in all cases.

メモリ最適化テーブルでのトランザクションに固有のエラー条件については、「 競合の検出と再試行ロジック」のセクションに移動してください。For error conditions specific to transactions on memory-optimized tables, jump to the section Conflict Detection and Retry Logic.

詳細については、「 SET TRANSACTION ISOLATION LEVEL (Transact-SQL)」を参照してください。For general information, see SET TRANSACTION ISOLATION LEVEL (Transact-SQL).

ペシミスティックとオプティミスティックPessimistic versus Optimistic

トランザクションの整合性へのアプローチがオプティミスティックかペシミスティックかによって、機能は異なってきます。The functional differences are due to pessimistic versus optimistic approaches to transaction integrity. メモリ最適化テーブルでは、オプティミスティック アプローチが使用されます。Memory-optimized tables use the optimistic approach:

  • ペシミスティック アプローチでは、潜在的な競合を、それが発生する前にロックを使ってブロックします。Pessimistic approach uses locks to block potential conflicts before they occur. ステートメントが実行されるときにロックが取得され、トランザクションがコミットされるとロックが解放されます。Lock are taken when the statement is executed, and released when the transaction is committed.

  • オプティミスティック アプローチでは、競合がその発生時に検出され、コミット時に検証チェックが実行されます。Optimistic approach detects conflicts as they occur, and performs validation checks at commit time.

    • メモリ最適化テーブルに対しては、エラー 1205 (デッドロック) は発生しません。Error 1205, a deadlock, cannot occur for a memory-optimized table.

オプティミスティック アプローチはオーバーヘッドが少なく、通常はより効率的です。これは 1 つには、トランザクションの競合がほとんどのアプリケーションであまり発生しないためです。The optimistic approach is less overhead and is usually more efficient, partly because transaction conflicts are uncommon in most applications. ペシミスティック アプローチとオプティミスティック アプローチの機能上の主な違いは、競合が発生した場合に、ペシミスティック アプローチでは待機するのに対し、オプティミスティック アプローチでは、トランザクションの 1 つが失敗し、クライアントがそのトランザクションを再試行する必要があるという点です。The main functional difference between the pessimistic and optimistic approaches is that if a conflict occurs, in the pessimistic approach you wait, while in the optimistic approach one of the transactions fails and needs to be retried by the client. 機能の違いは、REPEATABLE READ 分離レベルが有効だとさらに大きくなり、SERIALIZABLE レベルで最大になります。The functional differences are bigger when the REPEATABLE READ isolation level is in force, and are biggest for the SERIALIZABLE level.

トランザクション開始モードTransaction Initiation Modes

SQL Server のトランザクション開始モードは次のとおりです。SQL Server has the following modes for transaction initiation:

  • オートコミット - シンプルなクエリまたは DML ステートメントが開始されると、トランザクションが暗黙的に開かれ、ステートメントが終了すると、トランザクションが暗黙的にコミットされます。Autocommit - The start of a simple query or DML statement implicitly opens a transaction, and the end of the statement implicitly commits the transaction. 既定値は自動コミットです。Autocommit is the default.

    • オートコミット モードでは、通常、FROM 句で、メモリ最適化テーブルのトランザクション分離レベルに関するテーブル ヒントをコーディングする必要はありません。In autocommit mode, usually you are not required to code a table hint about the transaction isolation level on the memory-optimized table in the FROM clause.
  • Explicit - Transact-SQL には、BEGIN TRANSACTION コードと共に最終的な COMMIT TRANSACTION コードが含まれています。Explicit - Your Transact-SQL contains the code BEGIN TRANSACTION, along with an eventual COMMIT TRANSACTION. 2 つ以上のステートメントを、同じトランザクションに含めることができます。Two or more statements can be corralled into the same transaction.

    • Explicite モードでは、データベース オプションの MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT を使用するか、FROM 句でメモリ最適化テーブルのトランザクション分離レベルに関するテーブル ヒントをコーディングする必要があります。In explicit mode, you must either use the database option MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT or code a table hint about the transaction isolation level on the memory-optimized table in the FROM clause.
  • Implicit - SET IMPLICIT_TRANSACTION ON が有効の場合。Implicit - When SET IMPLICIT_TRANSACTION ON is in force. おそらく、IMPLICIT_BEGIN_TRANSACTION という名前の方が適切です。このオプションでは、0 = @@trancount の場合に、各 UPDATE ステートメントの前で、明示的な BEGIN TRANSACTION と同じことを暗黙的に実行するからです。Perhaps a better name would have been IMPLICIT_BEGIN_TRANSACTION, because all this option does is implicitly perform the equivalent of an explicit BEGIN TRANSACTION before each UPDATE statement if 0 = @@trancount. したがって、明示的な COMMIT TRANSACTION を最終的に発行するかどうかは、T-SQL コード次第です。Therefore it is up to your T-SQL code to eventually issue an explicit COMMIT TRANSACTION.

  • ATOMIC ブロック - ATOMIC ブロックのすべてのステートメントは、常に 1 つのトランザクションとして実行されます。ATOMIC BLOCK - All statements in ATOMIC blocks always run as part of a single transaction. ATOMIC ブロックのアクションは成功した場合に全体がコミットされるか、エラー発生時にすべてがロールバックされるかのどちらかです。Either the actions of the atomic block as a whole are committed on success, or the actions are all rolled back when a failure occurs. それぞれのネイティブ コンパイル ストアド プロシージャには ATOMIC ブロックが必要です。Each natively compiled stored procedure requires an ATOMIC block.

Explicit モードのコード例Code Example with Explicit Mode

解釈された Transact-SQL スクリプトでは次を使用します。The following interpreted Transact-SQL script uses:

  • 明示的なトランザクション。An explicit transaction.
  • dbo.Order_mo という名前のメモリ最適化テーブル。A memory-optimized table, named dbo.Order_mo.
  • READ COMMITTED トランザクション分離レベルのコンテキスト。The READ COMMITTED transaction isolation level context.

したがって、メモリ最適化テーブルにテーブル ヒントが必要です。Therefore it is necessary to have a table hint on the memory-optimized table. ヒントは SNAPSHOT またはさらに高い分離レベルを対象にしている必要があります。The hint must be for SNAPSHOT or an even more isolating level. コード例の場合、ヒントは WITH (SNAPSHOT) です。In the case of the code example, the hint is WITH (SNAPSHOT). このヒントが削除されている場合、スクリプトでは、41368 エラー (自動再試行が不適切) が発生します。If this hint is removed, the script would suffer an error 41368, for which an automated retry would be inappropriate:

エラー 41368Error 41368

READ COMMITTED 分離レベルを使用してメモリ最適化テーブルにアクセスする機能は、オートコミット トランザクションでのみサポートされます。Accessing memory optimized tables using the READ COMMITTED isolation level is supported only for autocommit transactions. 明示的なトランザクションおよび暗黙的なトランザクションではサポートされていません。It is not supported for explicit or implicit transactions. WITH (SNAPSHOT) などのテーブル ヒントを使用して、メモリ最適化テーブルでサポートされる分離レベルを指定します。Provide a supported isolation level for the memory-optimized table using a table hint, such as WITH (SNAPSHOT).

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;  
GO  

BEGIN TRANSACTION;  -- Explicit transaction.  

-- Order_mo  is a memory-optimized table.  
SELECT * FROM  
           dbo.Order_mo  as o  WITH (SNAPSHOT)  -- Table hint.  
      JOIN dbo.Customer  as c  on c.CustomerId = o.CustomerId;  
COMMIT TRANSACTION;

データベース オプション MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT を使用することで、WITH (SNAPSHOT) ヒントの必要はなくなります。The need for the WITH (SNAPSHOT) hint can be avoided through the use of the database option MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT. このオプションを ONに設定すると、低い分離レベルでのメモリ最適化テーブルへのアクセスは、自動的に SNAPSHOT 分離に昇格されます。When this option is set to ON, access to a memory-optimized table under a lower isolation level is automatically elevated to SNAPSHOT isolation.

ALTER DATABASE CURRENT
    SET MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT = ON;

行のバージョン管理Row Versioning

メモリ最適化テーブルでは高度な行バージョン管理システムが使用され、最も厳密な分離レベル SERIALIZABLE でも、効率的なオプティミスティック アプローチが実現します。Memory-optimized tables use a highly sophisticated row versioning system that makes the optimistic approach efficient, even at the most strict isolation level of SERIALIZABLE. 詳細については、「 メモリ最適化テーブルの概要」を参照してください。For details see Introduction to Memory-Optimized Tables.

READ_COMMITTED_SNAPSHOT または SNAPSHOT 分離レベルが有効な場合は、行バージョン管理システムがディスク ベースのテーブルに間接的に含まれます。Disk-based tables indirectly have a row versioning system when READ_COMMITTED_SNAPSHOT or the SNAPSHOT isolation level is in effect. このシステムは tempdb に基づいています。一方、メモリ最適化データ構造には、最大限の効率を得るために、行バージョン管理が組み込まれています。This system is based on tempdb, while memory-optimized data structures have row versioning built in, for maximum efficiency.

分離レベルIsolation Levels

次の表は、トランザクション分離のレベルを、分離が少ないものから順に示しています。The following table lists the possible levels of transaction isolation, in sequence from least isolation to most. 発生する可能性のある競合、およびこれらの競合を処理するための再試行ロジックの詳細については、「 競合の検出と再試行ロジック」を参照してください。For details about conflicts that can occur and retry logic to deal with these conflicts, see Conflict Detection and Retry Logic.

[分離レベル]Isolation Level [説明]Description
READ UNCOMMITTEDREAD UNCOMMITTED 使用できません: Read Uncommitted 分離ではメモリ最適化テーブルにアクセスできません。Not available: memory-optimized tables cannot be accessed under Read Uncommitted isolation. この場合でも、セッション レベル TRANSACTION ISOLATION LEVEL が READ UNCOMMITTED に設定されていれば、WITH (SNAPSHOT) テーブル ヒントを使用するか、データベース設定 MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT を ON に設定することにより、SNAPSHOT 分離でメモリ最適化テーブルにアクセスすることができます。It is still possible to access memory-optimized tables under SNAPSHOT isolation if the session-level TRANSACTION ISOLATION LEVEL is set to READ UNCOMMITTED, by using the WITH (SNAPSHOT) table hint or setting the database setting MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT to ON.
READ COMMITTEDREAD COMMITTED オートコミット モードが有効の場合にのみ、メモリ最適化テーブルに対してサポートされます。Supported for memory-optimized tables only when the autocommit mode is in effect. この場合でも、セッション レベル TRANSACTION ISOLATION LEVEL が READ COMMITTED に設定されていれば、WITH (SNAPSHOT) テーブル ヒントを使用するか、データベース設定 MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT を ON に設定することにより、SNAPSHOT 分離でメモリ最適化テーブルにアクセスすることができます。It is still possible to access memory-optimized tables under SNAPSHOT isolation if the session-level TRANSACTION ISOLATION LEVEL is set to READ COMMITTED, by using the WITH (SNAPSHOT) table hint or setting the database setting MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT to ON.

データベース オプション READ_COMMITTED_SNAPSHOT が ON に設定されている場合は、同じステートメント内でメモリ最適化テーブルとディスク ベースのテーブルの両方に READ COMMITTED 分離でアクセスすることはできません。If the database option READ_COMMITTED_SNAPSHOT is set to ON, it is not allowed to access both a memory-optimized and a disk-based table under READ COMMITTED isolation in the same statement.
SNAPSHOTSNAPSHOT メモリ最適化テーブルでサポートされます。Supported for memory-optimized tables.

内部的には、SNAPSHOT は、メモリ最適化テーブルを対象とした最も要求が少ないトランザクション分離レベルです。Internally SNAPSHOT is the least demanding transaction isolation level for memory-optimized tables.

SNAPSHOT が使用するシステム リソースは、REPEATABLE READ または SERIALIZABLE での使用量を下回ります。SNAPSHOT uses fewer system resources than does REPEATABLE READ or SERIALIZABLE.
REPEATABLE READREPEATABLE READ メモリ最適化テーブルでサポートされます。Supported for memory-optimized tables. REPEATABLE READ 分離では、同時実行トランザクションはこのトランザクションが読み取ったどの行もコミット時に更新していないということが保証されます。The guarantee provided by REPEATABLE READ isolation is that, at commit time, no concurrent transaction has updated any of the rows read by this transaction.

オプティミスティック モデルであるため、このトランザクションが読み取った行を同時実行トランザクションが更新することは妨げられません。Because of the optimistic model, concurrent transactions are not prevented from updating rows read by this transaction. 代わりに、REPEATABLE READ 分離に違反していないことをコミット時にこのトランザクションが検証しています。Instead, at commit time this transaction validated that REPEATABLE READ isolation has not been violated. 違反している場合、このトランザクションはロールバックされるため、再試行する必要があります。If it has, this transaction is rolled back and must be retried.
SERIALIZABLESERIALIZABLE メモリ最適化テーブルでサポートされます。Supported for memory-optimized tables.

分離が厳密すぎるため、トランザクションが同時ではなくほぼ順番に実行されることから、 Serializable という名前が付いています。Named Serializable because the isolation is so strict that it is almost a bit like having the transactions run in series rather than concurrently.

トランザクション フェーズと有効期間Transaction Phases and Lifetime

メモリ最適化テーブルが関係している場合、トランザクションの有効期間は次の図に示すようなフェーズを辿ります。When a memory-optimized table is involved, the lifetime of a transaction progresses through the phases as displayed in the following image:

hekaton_transactions

各フェーズの説明は次のとおりです。Descriptions of the phases follow.

通常の処理:フェーズ 1 (1/3)Regular Processing: Phase 1 (of 3)

  • このフェーズは、すべてのクエリとクエリ内の DML ステートメントの実行で構成されます。This phase is composed of the execution of all queries and DML statements in the query.
  • このフェーズでは、トランザクションの論理的開始時点のメモリ最適化テーブルのバージョンをステートメントが調べます。During this phase, the statements see the version of the memory-optimized tables as of the logical start time of the transaction.

検証:フェーズ 2 (2/3)Validation: Phase 2 (of 3)

  • 終了時刻を割り当て、それによってトランザクションに論理的完了とマークすると、検証フェーズが始まります。The validation phase begins by assigning the end time, thereby marking the transaction as logically complete. この完了により、このトランザクションと依存関係があるその他のトランザクションに、トランザクションのすべての変更内容が表示されます。This completion makes all changes of the transaction visible to other transactions which take a dependency on this transaction. 従属トランザクションは、このトランザクションが正常にコミットされるまではコミットできません。The dependent transactions are not allowed to commit until this transaction has successfully committed. さらに、このような依存関係を保持するトランザクションは、結果セットをクライアントに返すことはできません。データベースに正常にコミットされたデータのみ、クライアントが参照するようにするためです。In addition, transactions which hold such dependencies are not allowed to return result sets to the client, to ensure the client only sees data that has been successfully committed to the database.
  • このフェーズは、repeatable read と serializable の検証で構成されます。This phase comprises the repeatable read and serializable validation. repeatable read の検証では、トランザクションによって読み取られた行のいずれかが以降更新されたかどうかがチェックされます。For repeatable read validation, it checks whether any of the rows read by the transaction has since been updated. serializable の検証では、このトランザクションによってスキャンされたいずれかのデータ範囲に行が挿入されたかどうかがチェックされます。For serializable validation it checks whether any row has been inserted into any data range scanned by this transaction. スナップショット分離の使用時は、一意キー制約と外部キー制約の整合性を検証するために、「分離レベルと競合」の表に従って、repeatable read と serializable の両方の検証が行われることがあります。Per the table in Isolation Levels and Conflicts, both repeatable read and serializable validation can happen when using snapshot isolation, to validate consistency of unique and foreign key constraints.

コミット処理:フェーズ 3 (3/3)Commit Processing: Phase 3 (of 3)

  • コミット フェーズでは、持続性のあるテーブルへの変更がログに書き込まれ、そのログはディスクに書き込まれます。During the commit phase, the changes to durable tables are written to the log, and the log is written to disk. その後、制御がクライアントに返されます。Then control is returned to the client.
  • コミット処理が完了すると、すべての従属トランザクションにコミット可能であることが通知されます。After commit processing completes, all dependent transactions are notified that they can commit.

いつものように、トランザクションの作業単位は、データ ニーズに合わせてできるだけシンプルに、かつ小さくまとめてください。As always, you should try to keep your transactional units of work as minimal and brief as is valid for your data needs.

競合の検出と再試行ロジックConflict Detection and Retry Logic

トランザクションが失敗してロールバックが行われる原因となるトランザクション関連のエラー条件には、2 種類あります。There are two kinds of transaction-related error conditions that cause a transaction to fail and roll back. ほとんどの場合、このようなエラーが発生したら、デッドロックが発生したときと同様に、トランザクションを再試行する必要があります。In most cases, once such a failure occurs, the transaction needs to be retried, similar to when a deadlock occurs.

  • 同時実行トランザクション間の競合。Conflicts between concurrent transactions. これらは更新の競合と検証のエラーであり、トランザクション分離レベル違反や制約違反が原因として考えられます。These are update conflicts and validation failures, and can be due to transaction isolation level violations or constraint violations.
  • 依存関係のエラー。Dependency failures. これらは、依存するトランザクションのコミットが失敗したこと、または依存関係の数が大きくなりすぎたことに起因します。These result from transactions that you depend on failing to commit, or from the number of dependencies growing too large.

メモリ最適化テーブルにアクセスするトランザクションの失敗の原因となるエラー条件を以下に示します。The following are the error conditions that can cause transactions to fail when they access memory-optimized tables.

エラー コードError Code [説明]Description 原因Cause
4130241302 現在のトランザクションが開始されてから別のトランザクションで更新された行を更新しようとしました。Attempted to update a row that was updated in a different transaction since the start of the present transaction. このエラー条件は、2 つの同時実行トランザクションが同時に同じ行を更新または削除しようとした場合に発生します。This error condition occurs if two concurrent transactions attempt to update or delete the same row at the same time. 2 つのトランザクションのうちの 1 つがこのエラー メッセージを受け取り、そのトランザクションは再試行が必要になります。One of the two transactions receives this error message and will need to be retried.

4130541305 REPEATABLE READ の検証の失敗。Repeatable read validation failure. このトランザクションがメモリ最適化テーブルから読み取った行が、このトランザクションのコミット前にコミットした別のトランザクションによって更新されました。A row read from a memory-optimized table this transaction has been updated by another transaction that has committed before the commit of this transaction. このエラーは、REPEATABLE READ 分離または SERIALIZABLE 分離の使用時に発生することがあります。また、同時実行トランザクションのアクションが FOREIGN KEY 制約の違反を引き起こした場合も発生する可能性があります。This error can occur when using REPEATABLE READ or SERIALIZABLE isolation, and also if the actions of a concurrent transaction cause violation of a FOREIGN KEY constraint.

外部キー制約のこのような同時違反はまれであり、一般的にはアプリケーション ロジックまたはデータ エントリの問題を示しています。Such concurrent violation of foreign key constraints is rare, and typically indicates an issue with the application logic or with data entry. ただし、FOREIGN KEY 制約に関係する列のインデックスが存在しない場合も、このエラーが発行する可能性があります。However, the error can also occur if there is no index on the columns involved with the FOREIGN KEY constraint. したがって、メモリ最適化テーブルでは、外部キー列のインデックスを必ず作成するようにしてください。Therefore, the guidance is to always create an index on foreign key columns in a memory-optimized table.

外部キー違反によって発生する検証エラーに関する考慮事項の詳細については、SQL Server Customer Advisory Team による このブログ投稿 を参照してください。For more detailed considerations about validation failures caused by foreign key violations, see this blog post by the SQL Server Customer Advisory Team.
4132541325 SERIALIZABLE の検証の失敗。Serializable validation failure. 以前スキャンされた範囲に、現在のトランザクションによって新しい行が挿入されました。A new row was inserted into a range that was scanned earlier by the present transaction. これはファントム行と呼ばれます。We call this a phantom row. このエラーは、SERIALIZABLE 分離の使用時に発生することがあります。また、同時実行トランザクションのアクションが PRIMARY KEY、UNIQUE、または FOREIGN KEY 制約の違反を引き起こした場合も発生する可能性があります。This error can occur when using SERIALIZABLE isolation, and also if the actions of a concurrent transaction cause violation of a PRIMARY KEY, UNIQUE, or FOREIGN KEY constraint.

このような同時制約違反はまれであり、一般的にはアプリケーション ロジックまたはデータ エントリの問題を示しています。Such concurrent constraint violation is rare, and typically indicates an issue with the application logic or data entry. ただし、repeatable read の検証エラーと同様に、関係する列のインデックスが指定されていない FOREIGN KEY 制約が存在する場合も、このエラーが発生する可能性があります。However, similar to repeatable read validation failures, this error can also occur if there is a FOREIGN KEY constraint with no index on the columns involved.
4130141301 依存関係のエラー: 後でコミットに失敗した別のトランザクションに依存していました。Dependency failure: a dependency was taken on another transaction that later failed to commit. このトランザクション (Tx1) は別のトランザクション (Tx2) が書き込んだデータを読み取ることによって、そのトランザクション (Tx2) への依存関係ができましたが、Tx2 は自身の検証またはコミット処理のフェーズでした。This transaction (Tx1) took a dependency on another transaction (Tx2) while that transaction (Tx2) was in its validation or commit processing phase, by reading data that was written by Tx2. Tx2 はその後コミットに失敗しました。Tx2 subsequently failed to commit. Tx2 がコミットに失敗する最も一般的な原因は、repeatable read (41305) および serializable (41325) 検証エラーです。まれな原因として、ログ IO エラーがあります。Most common causes for Tx2 to fail to commit are repeatable read (41305) and serializable (41325) validation failures; a less common cause is log IO failure.
418234184041823 and 41840 メモリ最適化テーブルとテーブル変数のユーザー データ クォータに到達しました。Quota for user data in memory-optimized tables and table variables was reached. エラー 41823 は SQL Server Express/Web/Standard Edition と Azure SQL データベースAzure SQL Database の単一データベースに適用されます。Error 41823 applies to SQL Server Express/Web/Standard Edition, as well as single databases in Azure SQL データベースAzure SQL Database. エラー 41840 は Azure SQL データベースAzure SQL Database のエラスティック プールに適用されます。Error 41840 applies to elastic pools in Azure SQL データベースAzure SQL Database.

ほとんどの場合、これらのエラーは、ユーザー データの最大サイズに到達したことを示します。エラーを解決する方法は、メモリ最適化テーブルからデータを削除することです。In most cases these errors indicate that the maximum user data size was reached, and the way to resolve the error is to delete data from memory-optimized tables. ただし、このエラーが一時的なものに過ぎないことがまれにあります。However, there are rare cases where this error is transient. そのため、最初にエラーに遭遇したとき、再試行をお勧めします。We therefore recommend to retry when first encountering these errors.

この一覧にある他のエラーと同様に、41823 と 41840 はアクティブなトランザクションを中止させます。Like the other errors in this list, errors 41823 and 41840 cause the active transaction to abort.
4183941839 トランザクションがコミット依存関係の最大数を超えました。Transaction exceeded the maximum number of commit dependencies. 適用対象: SQL Server 2016 (13.x)SQL Server 2016 (13.x)」を参照してください。Applies to: SQL Server 2016 (13.x)SQL Server 2016 (13.x). SQL ServerSQL ServerAzure SQL データベースAzure SQL Database の後続版には、コミット依存関係の数に上限がありません。Later versions of SQL ServerSQL Server and Azure SQL データベースAzure SQL Database do not have a limit on the number of commit dependencies.

ある特定のトランザクション (Tx1) が依存できるトランザクションの数には制限があります。There is a limit on the number of transactions a given transaction (Tx1) can depend on. そのようなトランザクションは出力依存関係です。Those transactions are the outgoing dependencies. また、ある特定のトランザクション (Tx1) に依存できるトランザクションの数にも制限があります。In addition, there is a limit on the number of transactions that can depend on a given transaction (Tx1). そのようなトランザクションは入力依存関係です。These transactions are the incoming dependencies. 両方とも 8 が限度です。The limit for both is 8.

このエラーの最も一般的なケースは、1 つの書き込みトランザクションによって書き込まれたデータに多数の読み取りトランザクションがアクセスする場合です。The most common case for this failure is where there is a large number of read transactions accessing data written by a single write transaction. 同じデータの大規模スキャンを読み取りトランザクションがすべて実行している場合、および書き込みトランザクションの検証またはコミット処理に時間がかかる場合は、この条件が発生する可能性が高くなります。たとえば、書き込みトランザクションが serializable 分離で大規模スキャンを実行します (検証フェーズが長くなる)。また、トランザクション ログが低速ログ IO デバイスに置かれます (コミット処理が長くなる)。The likelihood of hitting this condition increases if the read transactions are all performing large scans of the same data and if validation or commit processing of the write transaction takes long, for example the write transaction performs large scans under serializable isolation (increases length of the validation phase) or the transaction log is placed on a slow log IO device (increases length of commit processing). 読み取りトランザクションが大規模スキャンを実行しているものの、数行しかアクセスしないと思われる場合、インデックスが欠落している可能性があります。If the read transactions are performing large scans and they are expected to access only few rows, an index might be missing. 同様に、書き込みトランザクションが serializable 分離を使用して大規模スキャンを実行しているものの、数行しかアクセスしないと思われる場合も、このエラーは、インデックスの欠落を示しています。Similarly, if the write transaction uses serializable isolation and is performing large scans but is expected to access only few rows, this is also an indication of a missing index.

コミット依存関係の数の制限は、トレース フラグ 9926 を使用することによって引き上げることができます。The limit on number of commit dependencies can be lifted by using Trace Flag 9926. このトレース フラグは、インデックスが欠落していないことを確認した後もこのエラー条件が発生する場合のみ使用してください。上記のケースにおけるこうした問題が隠されてしまう可能性があるからです。Use this trace flag only if you are still hitting this error condition after confirming that there are no missing indexes, as it could mask these issues in the above-mentioned cases. もう 1 つの注意点は、依存関係グラフが複雑になると、システムの非効率につながる可能性があるということです。各トランザクションの入力依存関係と出力依存関係の両方の数が大きくなり、個々のトランザクションに依存関係の層が多数存在するようになるからです。Another caution is that complex dependency graphs, where each transaction has a large number of incoming as well as outgoing dependencies, and individual transactions have many layers of dependencies, can lead to inefficiencies in the system.

再試行ロジックRetry Logic

上記の条件のいずれかが原因でトランザクションが失敗した場合は、そのトランザクションを再試行する必要があります。When a transaction fails due to any of the above-mentioned conditions, the transaction should be retried.

再試行ロジックは、クライアント側またはサーバー側に実装できます。Retry logic can be implemented at the client or server side. 一般的には、クライアント側に再試行ロジックを実装することをお勧めします。この方がより効率的であり、トランザクションが返した結果セットをエラーが発生する前に処理できるからです。The general recommendation is to implement retry logic on the client side, as it is more efficient, and allows you to deal with result sets returned by the transaction before the failure occurs.

再試行 T-SQL コードの例Retry T-SQL Code Example

T-SQL を使用したサーバー側の再試行ロジックは、結果セットをクライアントに返さないトランザクションでのみ使用してください。Server-side retry logic using T-SQL should only be used for transactions that do not return result sets to the client. そうしないと、再試行によってクライアントに返されると想定された以上の結果セットが返される場合があります。Otherwise, retries can potentially result in additional result sets beyond those anticipated being returned to the client.

次の解釈された T-SQL スクリプトは、メモリ最適化テーブルに関するトランザクション競合に関連付けられたエラーの再試行ロジックを示しています。The following interpreted T-SQL script illustrates what retry logic can look like for the errors associated with transaction conflicts involving memory-optimized tables.

-- Retry logic, in Transact-SQL.
DROP PROCEDURE If Exists usp_update_salesorder_dates;
GO

CREATE PROCEDURE usp_update_salesorder_dates
AS
BEGIN
    DECLARE @retry INT = 10;

    WHILE (@retry > 0)
    BEGIN
        BEGIN TRY
            BEGIN TRANSACTION;

            UPDATE dbo.SalesOrder_mo WITH (SNAPSHOT)
                set OrderDate = GetUtcDate()
                where CustomerId = 42;

            UPDATE dbo.SalesOrder_mo WITH (SNAPSHOT)
                set OrderDate = GetUtcDate()
                where CustomerId = 43;

            COMMIT TRANSACTION;

            SET @retry = 0;  -- //Stops the loop.
        END TRY

        BEGIN CATCH
            SET @retry -= 1;

            IF (@retry > 0 AND
                ERROR_NUMBER() in (41302, 41305, 41325, 41301, 41823, 41840, 41839, 1205)
                )
            BEGIN
                IF XACT_STATE() = -1
                    ROLLBACK TRANSACTION;

                WAITFOR DELAY '00:00:00.001';
            END
            ELSE
            BEGIN
                PRINT 'Suffered an error for which Retry is inappropriate.';
                THROW;
            END
        END CATCH

    END -- //While loop
END;
GO

--  EXECUTE usp_update_salesorder_dates;

複数コンテナーにまたがるトランザクションCross-Container Transaction

次の場合、トランザクションは複数コンテナーにまたがるトランザクションと呼ばれます。A transaction is called a cross-container transaction if it:

  • 解釈された Transact-SQL のメモリ最適化テーブルにアクセスする。Accesses a memory-optimized table from interpreted Transact-SQL; or
  • トランザクションが既に開いているときに、ネイティブ プロシージャを実行する (XACT_STATE() = 1)。Executes a native proc when a transaction is already open (XACT_STATE() = 1).

「複数コンテナーにまたがる」という用語は、2 つのトランザクション管理コンテナー (1 つはディスク ベースのテーブル用、もう 1 つはメモリ最適化テーブル用) にまたがってトランザクションが実行されることに由来します。The term "cross-container" derives from the fact that the transaction runs across the two transaction management containers, one for disk-based tables and one for memory-optimized tables.

複数コンテナーにまたがる単一のトランザクション内で、ディスク ベースのテーブルへのアクセスとメモリ最適化テーブルへのアクセスに、それぞれ異なる分離レベルを使用できます。Within a single cross-container transaction, different isolation levels can be used for accessing disk-based and memory-optimized tables. この違いは、WITH (SERIALIZABLE) のような明示的なテーブル ヒントか、データベース オプション MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT によって表されます。このデータベース オプションを使用すると、TRANSACTION ISOLATION LEVEL が READ COMMITTED または READ UNCOMMITTED として構成されていれば、メモリ最適化テーブルの分離レベルが暗黙的にスナップショットに昇格されます。This difference is expressed through explicit table hints such as WITH (SERIALIZABLE) or through the database option MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT, which implicitly elevates the isolation level for memory-optimized table to snapshot if the TRANSACTION ISOLATION LEVEL is configured as READ COMMITTED or READ UNCOMMITTED.

Transact-SQL コードの例を次に示します。In the following Transact-SQL code example:

  • ディスク ベースのテーブル Table_D1 は、READ COMMITTED 分離レベルを使用してアクセスされます。The disk-based table, Table_D1, is accessed using the READ COMMITTED isolation level.
  • メモリ最適化テーブル Table_MO7 は、SERIALIZABLE 分離レベルを使用してアクセスされます。The memory-optimized table Table_MO7 is accessed using the SERIALIZABLE isolation level. Table_MO6 には特定の分離レベルが関連付けられていません。挿入は常に一貫しており、基本的に serializable 分離で実行されるからです。Table_MO6 does not have a specific associated isolation level, since inserts are always consistent and executed essentially under serializable isolation.
-- Different isolation levels for
-- disk-based tables versus memory-optimized tables,
-- within one explicit transaction.

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
go

BEGIN TRANSACTION;

    -- Table_D1 is a traditional disk-based table, accessed using READ COMMITTED isolation.

    SELECT * FROM Table_D1;


    -- Table_MO6 and Table_MO7 are memory-optimized tables.
    -- Table_MO7 is accessed using SERIALIZABLE isolation,
    --   while Table_MO6 does not have a specific isolation level.

    INSERT Table_MO6
        SELECT * FROM Table_MO7 WITH (SERIALIZABLE);

COMMIT TRANSACTION;
go

制限事項Limitations

  • 複数データベースにまたがるトランザクションは、メモリ最適化テーブルではサポートされません。Cross-database transactions are not supported for memory-optimized tables. トランザクションがメモリ最適化テーブルにアクセスする場合、そのトランザクションは、他のデータベースにはアクセスできません。ただし次を除きます。If a transaction accesses a memory-optimized table, the transaction cannot access any other database, except for:

    • tempdb データベース。tempdb database.
    • マスター データベースからの読み取り専用。Read-only from the master database.
  • 分散トランザクションはサポートされていません。BEGIN DISTRIBUTED TRANSACTION が使用されている場合、トランザクションは、メモリ最適化テーブルにアクセスできません。Distributed transactions are not supported: When BEGIN DISTRIBUTED TRANSACTION is used, the transaction cannot access a memory-optimized table.

ネイティブ コンパイル ストアド プロシージャNatively Compiled Stored Procedures

  • ネイティブ プロシージャでは、次のように、ATOMIC ブロックが、ブロック全体に対してトランザクション分離レベルを宣言する必要があります。In a native proc, the ATOMIC block must declare the transaction isolation level for the whole block, such as:

    • ... BEGIN ATOMIC WITH (TRANSACTION ISOLATION LEVEL = SNAPSHOT, ...) ...
  • ネイティブ プロシージャの本文では、明示的なトランザクション制御ステートメントは許可されません。No explicit transaction control statements are allowed within the body of a native proc. BEGIN TRANSACTION、ROLLBACK TRANSACTION など、どれも許可されていません。BEGIN TRANSACTION, ROLLBACK TRANSACTION, and so on, are all disallowed.

  • ATOMIC ブロックに関するトランザクション制御の詳細については、「ATOMIC ブロック」を参照してくださいFor more information about transaction control with ATOMIC blocks, see Atomic Blocks