Click here to view and discuss this page in DocCommentXchange. In the future, you will be sent there automatically.

SQL Anywhere 11.0.1 (日本語) » SQL Anywhere サーバ - SQL の使用法 » データベースの作成 » トランザクションと独立性レベルの使用 » 独立性レベルと一貫性

 

スナップショット・アイソレーション

複数のユーザが同じデータに対して同時に読み込みと書き込みを行うと、ブロックやデッドロックが発生することがあります。スナップショット・アイソレーションは、さまざまなバージョンのデータを管理することにより同時実行性と一貫性を向上させる目的で設計されています。トランザクションでスナップショット・アイソレーションを使用すると、データベース・サーバは読み込み要求の応答としてコミットされたバージョンのデータを返します。これは読み込みロックを取得せずに行われるため、データを書き込んでいるユーザとの干渉は発生しません。

「スナップショット」とは、データベースでコミットされた一連のデータです。スナップショット・アイソレーションを使用すると、トランザクション内のすべてのクエリで同じデータのセットが使用されます。データベースのテーブルでロックは取得されません。これにより、他のトランザクションはブロックせずにアクセスして修正できます。SQL Anywhere では、スナップショットを作成するときに制御できる 3 つのスナップショット・アイソレーションのレベルをサポートしています。

  • snapshot   トランザクションが最初のローの読み込み、挿入、更新、または削除を行った時点から、コミットされたデータのスナップショットを使用します。

  • statement-snapshot   文で最初のローが読み込まれた時点から、コミットされたデータのスナップショットを使用します。トランザクション内の各文で参照されるデータのスナップショットはそれぞれ異なる時点のものになります。

  • readonly-statement-snapshot   読み込み専用の文についてのみ、最初のローが読み込まれた時点から、コミットされたデータのスナップショットを使用します。トランザクション内の各読み込み専用文で参照されるデータのスナップショットはそれぞれ異なる時点のものになります。挿入、更新、削除の文については、updatable_statement_isolation オプションに指定された独立性レベル (0 (デフォルト)、1、2、3 のいずれか) を使用します。

BEGIN SNAPSHOT 文を使用して、トランザクションのスナップショットの開始時に指定するオプションもあります。BEGIN SNAPSHOT 文を参照してください。

スナップショット・アイソレーションは、主に次のような場合に便利です。

  • 読み込みは多いが更新は少ないアプリケーション   スナップショット・トランザクションは、データベースを修正する文の場合のみ、書き込みロックを取得します。トランザクションが主に読み込み操作を実行する場合、スナップショット・トランザクションは、他のユーザと干渉する可能性のある読み込みロックを取得しません。

  • 他のユーザがデータにアクセスする必要があるにもかかわらず、時間がかかるトランザクションを実行するアプリケーション   スナップショット・トランザクションは読み込みロックを取得しないため、他のユーザはスナップショット・トランザクションの実行中にデータの読み込みや更新を実行できます。

  • データベースからの一貫したデータのセットを読み取る必要があるアプリケーション   スナップショットはある時点からのコミット済みデータのセットを表示するため、トランザクションの実行中に他のユーザが変更を加えた場合でも、スナップショット・アイソレーションを使用すれば、そのトランザクション内では変更されない一貫したデータを確認できます。

スナップショット・アイソレーションは、すべてのユーザが共有するベース・テーブルとグローバル・テンポラリ・テーブルのみに影響します。その他のテーブルの種類では読み込み操作を行っても、古いバージョンのデータは表示されず、スナップショットは開始されません。別のテーブルの種類に対する更新によってスナップショットが開始されるのは、isolation_level オプションが snapshot に設定されていて、更新によりトランザクションが開始される場合だけです。

文またはトランザクションのスナップショットを使用する、WITH HOLD 句を使用して開かれたカーソルがある場合、次の文は実行できません。

WITH HOLD 句でカーソルを開くと、スナップショットの開始時にコミットされたすべてのローのスナップショットが表示されます。カーソルを開いたトランザクションの開始以降の、現在の接続で完了された変更もすべて表示されます。

高速トランケーションが実行されない場合にのみ、TRUNCATE TABLE を使用できます。これは、このような場合に個別の DELETE がトランザクションログに記録されるためです。TRUNCATE 文を参照してください。

また、これらの文のいずれかをスナップショットでないトランザクションから実行した場合、すでに実行中のスナップショット・トランザクションで、それ以降にテーブルを使用しようとすると、スキーマが変更されたことを示すエラーが返されます。

トランザクションのスナップショットが開始された後でビューがリフレッシュされた場合、マテリアライズド・ビュー・マッチングではそのビューは使用されません。

スナップショット・アイソレーションのレベルは、すべてのプログラミング・インタフェースでサポートされています。スナップショット・アイソレーションのレベルは SET OPTION 文を使用して設定できます。スナップショット・アイソレーションの使用については、次の項を参照してください。

ロー・バージョン

スナップショット・アイソレーションがデータベースで有効になると、ローが更新されるたびに、データベース・サーバは元のローのコピーをテンポラリ・ファイルに格納されたバージョンに追加します。元のロー・バージョンのエントリは、元のロー値にアクセスする必要がある可能性のある、すべてのアクティブなスナップショット・トランザクションが完了するまで格納されます。スナップショット・アイソレーションを使用するトランザクションは、コミット済みの値だけを確認できます。そのため、スナップショット・トランザクションの開始前にローの更新がコミットされなかったかロールバックされた場合、スナップショット・トランザクションは元のロー値にアクセスできる必要があります。これにより、スナップショット・アイソレーションを使用するトランザクションは、基本となるテーブルにロックを設定せずにデータを閲覧できます。

VersionStorePages データベース・プロパティは、バージョン・ストア用に現在使用されているテンポラリ・ファイル内のページ数を返します。この値を取得するには、次のクエリを実行します。

SELECT DB_PROPERTY ( 'VersionStorePages' );

古いロー・バージョンのエントリは、不要になると削除されます。BLOB の古いバージョンは、不要になるまで、テンポラリ・ファイルではなく元のテーブルに格納されています。古いロー・バージョンのインデックス・エントリは、不要になるまで元のインデックスに格納されています。

テンポラリ・ファイル内の空き領域のサイズは、sa_disk_free_space システム・プロシージャを使用すると取得できます。sa_disk_free_space システム・プロシージャを参照してください。

ロー値を更新するトリガが起動されると、それらのローの元の値もテンポラリ・ファイルに格納されます。

短いトランザクションと短いスナップショットを使用するようにアプリケーションを設定すると、必要なテンポラリ・ファイルの領域は減少します。

テンポラリ・ファイルの増大に関心がある場合は、テンポラリ・ファイルが特定のサイズに達したときに実行するアクションを指定する GrowTemp システム・イベントを設定できます。システム・イベントの概要を参照してください。

スナップショット・トランザクションの知識

スナップショット・トランザクションは、更新時に書き込みロックを取得しますが、スナップショットを使用するトランザクションや文では読み込みロックを取得しません。その結果、読み込み処理は書き込み処理をブロックせず、書き込み処理は読み込み処理をブロックしません。ただし、書き込み処理は、同じローを更新しようとする他の書き込み処理をブロックすることがあります。

スナップショット・アイソレーションでは、BEGIN TRANSACTION 文でトランザクションが開始しません。トランザクションで使用されるスナップショット・アイソレーションのレベルに応じて、トランザクション内で最初の読み込み、挿入、更新、または削除時にトランザクションが開始します。次の例は、スナップショット・アイソレーションでトランザクションが開始するタイミングを示します。

SET OPTION PUBLIC.allow_snapshot_isolation = 'On';
         SET TEMPORARY OPTION isolation_level = 'snapshot';
   SELECT * FROM Products; --transaction begins and the statement only 
                           --sees changes that are already committed
   INSERT INTO Products 
         SELECT ID + 30, Name, Description,
         'Extra large', Color, 50, UnitPrice, NULL
         FROM Products
         WHERE Name = 'Tee Shirt';
COMMIT; --transaction ends

スナップショット・アイソレーションの有効化
スナップショット・アイソレーションの例
更新の競合とスナップショット・アイソレーション