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