メモリ最適化テーブルへのアクセスでは、使用できるトランザクション分離レベルは
- SNAPSHOT
- REPEATABLE READ
- SERIALIZABLE
の 3 種類になります。
SQL Server のデフォルトのトランザクション分離レベルは READ COMMITTED になります。
メモリ最適化テーブルでの READ COMMITTED のサポート状況は以下のようになっています。
READ COMMITTED 分離レベルは自動コミット トランザクションのメモリ最適化されたテーブルでサポートされます。 この分離レベルは、明示的または暗黙的なユーザー トランザクションではサポートされません。 自動コミット トランザクションが有効になっている、メモリ最適化テーブルについては、クエリがどのディスク ベース テーブルにもアクセスできない場合にのみ、分離レベル READ_COMMITTED_SNAPSHOT がサポートされます。 また、解釈された Transact-SQL を使用して SNAPSHOT 分離で開始されるトランザクションでは、メモリ最適化テーブルにアクセスできません。 解釈された Transact-SQL を使用して REPEATABLE READ 分離または SERIALIZABLE 分離で開始されるトランザクションでは、SNAPSHOT 分離を使用してメモリ最適化テーブルにアクセスする必要があります。 このシナリオの詳細については、「複数コンテナーにまたがるトランザクション」を参照してください。
READ COMMITTED は、SQL Server の既定の分離レベルです。 ただし、上で説明したように、READ COMMITTED 分離レベルは自動コミット トランザクションのメモリ最適化されたテーブルでサポートされます。 この分離レベルは、明示的または暗黙的なユーザー トランザクションではサポートされません。 既定の分離レベルが READ COMMITED 以下の場合は、次のいずれかの操作を実行できます。
SQL Server では自動コミットがデフォルトですが、この自動コミットであれば READ COMMITTED はサポートされています。
ですので、以下のようなクエリは分離レベルを意識しなくても実行することが可能です。
SELECT * FROM MemTable
それでは、以下のような明示的なトランザクションを指定したクエリを実行してみます。
BEGIN TRAN SELECT * FROM MemTable COMMIT TRAN
この場合は以下のようなエラーが発生します。
メッセージ 41368、レベル 16、状態 0、行 2 |
明示的なトランザクションを指定した場合にはテーブルヒントに SNAPSHOT を設定します。
BEGIN TRAN SELECT * FROM MemTable WITH(SNAPSHOT) COMMIT TRAN
この SNAPSHOT のテーブルヒントはメモリ最適化テーブル用のヒントになります。
メモリ最適化されたテーブルは、SNAPSHOT 分離でアクセスされます。 SNAPSHOT は、メモリ最適化されたテーブルだけで使用できまます (ディスク ベースのテーブルでは使用できません)。 詳細については、「トランザクション分離レベル」を参照してください。
SET TRANSACTION ISOLATION LEVEL にも SNAPSHOT はありますが、こちらを使ってもメモリ最適化テーブルにはアクセスをすることはできません。
メッセージ 41332、レベル 16、状態 0、行 2 |
CTP1 では SNAPSHOT をテーブルヒントとして指定していましたが、CTP2 になり、ALTER DATABASE に MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT というオプションが追加されました。
デフォルトでは無効になっているのですが有効にすると以下のように動作が変わります。
トランザクション分離レベルが SNAPSHOT より低い分離レベル (たとえば、READ COMMITTED または READ UNCOMMITTEDREAD) に設定されている場合は、メモリ最適化テーブル上で解釈されたすべての Transact-SQL 操作が SNAPSHOT 分離レベルで実行されます。 この動作は、トランザクション分離レベルがセッション レベルで明示的に設定されているか、既定値が暗黙的に使用されるかに関係なく実行されます。
このオプションが有効になっている場合は自動的に分離レベルがエスカレーションされますので、明示的なトランザクションを指定した場合もテーブルヒントを指定しないでもアクセスが可能となります。
ALTER DATABASE TESTDB SET MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT = ON GO BEGIN TRAN SELECT * FROM MemTable COMMIT TRAN
自動エスカレーションができると既存のクエリに手を加える箇所が少なくなりそうなので、この機能はいいですね~。