データベースが複数のトランザクションによってアクセスされる場合、データベースの同一データの読取りを処理するために、同時に行う変更を調整する方法が必要となります。TimesTenおよびTimesTen Cacheでは、トランザクションの独立性およびロックを使用して、データへの同時アクセスが調整されます。
この章の内容は次のとおりです。
トランザクションの独立性により、データベースへの同時接続が複数あったとしても、システムでは一度に1つのトランザクションを処理するように見えるアプリケーションを実現できます。アプリケーションは、Isolation
一般接続属性を使用して、接続の分離レベルを設定できます。同時接続では、異なる分離レベルを使用できます。
分離レベルと同時実行性は反比例します。分離レベルが低いほど、同時実行性は高まりますが、データの非一貫性のリスクが増大します。分離レベルが高いほど、データ一貫性の度合いは高まりますが、同時実行性は損なわれます。
TimesTenでは、次の2つの分離レベルがサポートされています。
アプリケーションでコミット読取り分離レベルを使用する場合、読取りアクセスで書込みデータの個別のコピーが使用されるため、ロックは必要ありません。コミット読取り分離レベルでは、問合せをブロックせずにシリアライズ可能分離レベルまたはコミット読取り分離レベルとの連携処理が可能です。書込みアクセスは、コミット読取り分離レベルが使用されている読取りアクセスはブロックしません。コミット読取り分離レベルがデフォルトの分離レベルです。コミット読取り分離レベルがデフォルトの分離レベルです。
TimesTenおよびTimesTen Cacheでは、コミット読取り分離レベルの実装にバージョニングが使用されます。TimesTenおよびTimesTen Cacheの更新処理では、待機せずに、更新する行に対してシリアライズ可能でない読取りを続行できるように、それらの行の新しいコピーが作成されます。
図4-1は、あるアプリケーションでデータのコミット済コピーの読取りが行われ、別のアプリケーションでコミットされていないコピーに対して書込みおよび読取りが行われていることを示しています。
読取りアクセスは書込みアクセスをブロックせず、書込みアクセスは読取りアクセスをブロックしないため、コミット読取り分離レベルは同時実行性を高めることができます。この分離レベルは、スキャン中の行にアクセスする必要がある他の処理と競合する可能性がある、スキャンの実行時間が長いアプリケーションにとって有効です。ただし、この分離レベルを使用する場合のデメリットは、トランザクション内で、あるいは単一の文(たとえば、ネステッド結合の内部ループ)であっても、複数の非リピータブル・リードが可能であることです。
この分離レベルを使用している場合、表を操作するDDL文は、その表に対する読取りアクセスと書込みアクセスをブロックできます。たとえば、アプリケーションで表の行を読み取ろうとしても、別のアプリケーションにその表に対してコミットしていないDROP TABLE
、CREATE INDEX
、またはALTER TABLE
操作が存在すると、読取りを実行できません。さらに、ブロッキング・チェックポイントによって、読取りアクセスと書込みアクセスがブロックされます。
コミット読取り分離レベルでは、マテリアライズド・ビューとそれらのディテール表との一貫性を保証するために、マテリアライズド・ビューのメンテナンス中に必要となる読取りロックを設定します。これらのロックは、トランザクションの終了まで保持されませんが、かわりにメンテナンスが完了した時点で解放されます。
アプリケーションでシリアライズ可能分離レベルを使用する場合、ロックはトランザクション内で取得され、読取りおよび書込みの両方のトランザクションのコミットまたはロールバックまで保持されます。そのため、あるトランザクションで読み取られた行は、そのトランザクションが完了するまで、別のトランザクションから更新または削除することはできません。同様に、あるトランザクションによって挿入、更新または削除された行は、そのトランザクションが完了するまで、別のトランザクションからはアクセスできません。
この分離レベルは、同時実行性を低下させて、トランザクション内のリピータブル・リードと独立性の向上を実現します。データベース・レベル・ロックが選択されている場合、トランザクションでは、シリアライズ可能分離レベルが使用されます。
図4-2は、トランザクションがコミットされるまでロックが保持されることを示しています。
シリアライズ可能分離レベルは、最強の分離レベルを必要とするトランザクションに有効です。読取りロックはトランザクションがコミットするまで保持されるため、トランザクションによって読み取られるデータを変更する必要がある同時実行アプリケーションでは、ロック・タイムアウトが発生する可能性があります。
ロックは、リソースへのアクセスをシリアライズして、あるユーザーによって参照中または変更中の要素が別のユーザーによって同時に変更されるのを防ぐために使用されます。TimesTenおよびTimesTen Cacheでは、すべてのデータベース・アクセスに対してロックが自動的に実行されます。
共有ロックでは、操作の種類に応じて、関連するリソースの共有が可能です(そのため、共有されている行、表またはビューを変更したり削除する必要はありません)。複数のトランザクションが同じリソースについて共有ロックを取得できます。
排他ロックでは、データベースでアクティブなトランザクションが常に1つしか存在しないようにします。このロックは、リソースがデータ変更のために共有されて取得されることを防止します。リソースを排他的にロックした最初のトランザクションは、トランザクションが完了してその排他ロックが解除されるまで、そのリソースを変更できる唯一のトランザクションになります。
シリアライズ可能トランザクションは、これらのトランザクションで読み取るアイテムに対して共有ロックを、これらのトランザクションで書き込むアイテムに対して排他ロックを取得します。これらのロックは、トランザクションがコミットまたはロールバックされるまで保持されます。コミット読取りトランザクションは、これらのトランザクションで書込みアイテムに対して排他ロックを取得し、トランザクションがコミットされるまでこれらのロックを保持します。コミット読取りトランザクションは、これらのトランザクションで読み取るアイテムに対してロックを取得しません。トランザクションをコミットまたはロールバックすると、すべてのカーソルが閉じられ、トランザクションによって保持されていたすべてのロックが解除されます。
TimesTenおよびTimesTen Cacheはデッドロック検出を行って、デッドロックの状況をレポートし、削除します。デッドロックのエラーが原因でロックを拒否された場合、アプリケーションはトランザクション全体をロールバックして再試行する必要があります。
アプリケーションでは、次の3つのロック・レベルから選択できます。
データベース・レベル・ロックは、トランザクションによるアクセス時にデータベース全体をロックします。すべてのデータベース・レベル・ロックは排他的です。データベース・レベル・ロックを必要とするトランザクションは、データベースにアクティブなトランザクションがなくなるまで開始できません。トランザクションでデータベース・レベル・ロックが取得されると、そのトランザクションがコミットまたはロールバックされるまで、他のすべてのトランザクションはブロックされます。
データベース・レベル・ロックは、表レベル・ロックより同時実行性を制限されるため、同時実行性が不要な場合にバルク・ロードなどの初期化処理でのみ有効です。データベース・レベル・ロックを使用すると、同時実行性およびスループットは低下しますが、行レベル・ロックまたは表レベル・ロックよりレスポンス時間が向上します。
異なるトランザクションは、異なるレベルのロックと共存できますが、データベース・レベル・ロックを使用しているトランザクションが1つでも存在すると、同時実行性が低下します。
データベース・レベル・ロックを実装するには、LockLevel
一般接続属性またはttLockLevel
組込みプロシージャを使用します。詳細は、『Oracle TimesTen In-Memory Databaseリファレンス』のttLockLevelに関する説明を参照してください。
表レベル・ロックは、トランザクションによってアクセスされている表をロックします。文が表内のほとんどの行にアクセスする場合に有効です。アプリケーションで、ttOptSetFlag
組込みプロシージャをコールして、オプティマイザで表ロックが使用されるようにリクエストできます。オプティマイザによって、表ロックが使用されるタイミングが決定されます。
注意: 詳細は、『Oracle TimesTen In-Memory Databaseリファレンス・ガイド』のttOptSetFlagに関する説明を参照してください。 |
表ロックは、スループットを低下させる可能性があるため、表の大部分をロックする必要がある場合または同時実行性が不要な場合にのみ使用します。たとえば、バルク更新などの処理では、表をロックできます。コミット読取り分離レベルの場合、TimesTenおよびTimesTen Cacheでは、アプリケーションによって明示的にリクエストされていないかぎり、読取り操作に対して表レベル・ロックは使用されません。
行レベル・ロックは、トランザクションによってアクセス中の行のみをロックします。同時実行トランザクションが同一表の行にアクセスできるようにすることで、最高の同時実行性を実現できます。行レベル・ロックは、同時実行トランザクションが多数あり、それぞれが同一表の異なる行で処理中の場合に最適です。
アプリケーションでは、LockLevel
一般接続属性、ttLockLevel
組込みプロシージャおよびttOptSetFlag
組込みプロシージャを使用して、行レベル・ロックを管理できます。
注意: 詳細は、『Oracle TimesTen In-Memory Databaseリファレンス』のttLockLevelに関する説明とttOptSetFlagに関する説明を参照してください。 |