データの同時実行性と整合性
このページのスクリプト・コンテンツはナビゲーションのみを目的としており、いかなる方法においても内容を変更するものではありません。
この章では、マルチユーザー・データベース環境におけるOracle AI Databaseでどのようにデータ整合性が維持されるかについて説明します。
-
データの同時実行性と整合性の概要シングル・ユーザーのデータベースでは、他のユーザーが同時に同じデータを変更することがないように、ユーザーはデータを変更できます。ただし、マルチユーザー・データベースでは、複数のトランザクション内の文によって、同じデータが同時に更新される可能性があります。同時に実行される複数のトランザクションでは、意味のある一貫した結果を出すことが必要です。
-
Oracle AI Databaseのトランザクション分離レベルの概要トランザクション分離レベルのANSI規格は、分離レベルごとに許可または防止される現象という観点で、定義されます。
-
Oracle AI Databaseのロック・メカニズムの概要ロックとは、破壊的な相互作用が起こらないようにするメカニズムです。
-
自動ロックの概要 Oracle AI Databaseのトランザクションは、トランザクションのかわりにリソースを自動的にロックし、同じリソースへの排他的アクセスを必要とする処理を他のトランザクションで実行しないようにします。
-
手動データ・ロックの概要 Oracle AI Databaseでは、手動でデフォルトのロック・メカニズムをオーバーライドできます。
-
ユーザー定義ロックの概要Oracle AI Databaseのロック・マネージメントのサービスを使用すると、特定のアプリケーションで独自のロックを定義できます。
データの同時実行性と整合性の概要
シングル・ユーザーのデータベースでは、他のユーザーが同時に同じデータを変更することがないように、ユーザーはデータを変更できます。ただし、マルチユーザー・データベースでは、複数のトランザクション内の文によって、同じデータが同時に更新される可能性があります。同時に実行される複数のトランザクションでは、意味のある一貫した結果を出すことが必要です。
マルチユーザー・データベースには次の機能が備わっている必要があります。
-
ユーザーが同時にデータにアクセスできることの保証(データ同時実行性)
-
ユーザー自身のトランザクションや他のユーザーのトランザクションによる参照可能な変更を含め、各ユーザーにデータの一貫したビューが表示されることの保証(データ整合性)
トランザクションの同時実行における一貫したトランザクション動作を説明するために、データベース調査者は、シリアライズ可能性と呼ばれるトランザクション分離モデルを定義しています。シリアライズ可能トランザクションは、他のユーザーがデータベースのデータを変更していないように見える環境内で動作します。
一般に、この程度までのトランザクションの分離が望ましいとされますが、シリアライズ可能モードで数多くのアプリケーションを実行すると、アプリケーションのスループットがかなり低下する可能性があります。同時に実行される各トランザクションの完全な分離とは、あるトランザクションが別のトランザクションによって問合せされている表への挿入を実行できないという状態を指します。つまり、現実には、トランザクションの完全な分離とパフォーマンスとの間の妥協点を考慮する必要があります。
Oracle AI Databaseでは、マルチバージョン一貫性モデルや様々なタイプのロックおよびトランザクションを使用することによって、データ整合性が維持されます。これにより、データベースが複数の同時ユーザーに対するデータのビューを提示する場合、それぞれ特定の時点において一貫性があるビューにすることができます。異なるバージョンのデータ・ブロックを同時に存在する場合があるため、トランザクションでは問合せに要求された時点でコミットされたデータのバージョンが読み取られ、あるある特定の時点において一貫性のある結果が戻されます。
-
マルチバージョンの読取り一貫性 Oracle AI Databaseでは、マルチバージョニングによって、データの複数のバージョンを同時にマテリアライズできます。Oracle AI Databaseでは、マルチバージョン読取り一貫性が維持されます。
-
ロックのメカニズム一般に、マルチユーザー・データベースでは、なんらかのデータ・ロックを使用してデータの同時実行性、一貫性、および整合性の問題を解決します。
-
ANSI/ISOトランザクション分離レベル ANSIおよびISO/IECの両方で採用されているSQL標準では、トランザクション分離レベルが4つ定義されます。これらのレベルは、トランザクション処理のスループットに与える影響の度合いが異なります。関連項目: 「データ整合性」および「トランザクション」
マルチバージョン読取り一貫性
Oracle AI Databaseでは、マルチバージョン機能によって、複数のバージョンのデータ が同時にマテリアライズされます。Oracle AI Databaseは、マルチバージョン読取り一貫性を維持します。
Oracleデータベースの問合せには、次の特性があります。
-
読取り一貫性問合せ
1回の問合せによって戻されるデータは、コミット済であり、1回の特定の時点での一貫性を保ちます。
Note: Oracle AI Database never permits a dirty read, which occurs when a transaction reads uncommitted data in another transaction.
内容を保証しない読取りの問題を具体的に説明するため、あるトランザクションが列値を更新し、その値がまだコミットされていない場合を考えます。2つ目のトランザクションによって、内容が保証されない更新された値(未コミットの値)が読み取られます。1つ目のセッションによってトランザクションがロールバックされ、列の値が古い値に戻されたとしても、2つ目のトランザクションでは更新された値が継続して使用されるため、データベースが破損します。内容を保証しない読取りでは、データ整合性が損われ、外部キーに違反し、一意制約が無視されます。
-
非ブロック化問合せ
データの読取り側と書込み側は、互いにブロックすることはありません。
-
文レベルの読取り一貫性Oracle AI Databaseでは、文レベルの読取り一貫性が常に適用されるため、1つの問合せによって戻されたデータがコミット済で、ある特定の時点で一貫していることが保証されます。
-
トランザクション・レベルの読取り一貫性 Oracle AI Databaseは、1つのトランザクションのすべての問合せに対して、トランザクション・レベルの読取り一貫性として知られる読取り一貫性を実現することもできます。
-
読取り一貫性とUNDOセグメントマルチバージョン読取り一貫性モデルを管理するには、表に対する問合せと更新が同時に実行されたときに、データベースによって読取り一貫性のある一連のデータが作成される必要があります。
-
読取り一貫性および遅延挿入 遅延挿入という特殊なタイプの挿入で、標準の読取り一貫性メカニズムは使用されません。関連項目: 「ロック動作の概要」
文レベルの読取り一貫性
Oracle AI Databaseでは、文レベルの読取り一貫性を常に適用することで、1つの問合せによって戻されたデータがコミット済で、ある特定の時点で一貫していることを保証します。
単一のSQL文の一貫性が保たれる基準となる時点は、トランザクション分離レベルおよび問合せの内容に応じて異なります。
-
コミット読取り分離レベルでは、この時点は文が開始されたときになります。たとえば、SCN 1000で
SELECT文が開始された場合、この文ではSCN 1000の時点での一貫性が保たれます。 -
シリアライズ可能または読取り専用トランザクションでは、この時点はトランザクションが開始されたときです。たとえば、複数の
SELECT文が実行されるトランザクションがSCN 1000で開始された場合、各文ではSCN 1000の時点での一貫性が保たれます。 -
フラッシュバック問合せ操作(
SELECT ... AS OF)では、SELECT文で特定の時点が明示的に指定されます。たとえば、先週の木曜日の2:00 p.m時点の表を問い合せることができます。
関連項目:フラッシュバック問合せについて学習するには、『Oracle AI Database開発ガイド』を参照してください。
トランザクション・レベルの読取り一貫性
Oracle AI Databaseは、1つのトランザクションのすべての問合せに対して、トランザクション・レベルの読取り一貫性と呼ばれます読取り一貫性を実現することもできます。
この場合、トランザクション内の各文には、同じ時点のデータが表示されます。これは、トランザクション開始時点です。
シリアライズ可能トランザクションによる問合せでは、そのトランザクション自体が変更したデータも参照できます。たとえば、employeesを更新し、employeesを問い合せたトランザクションには、その更新内容が反映されます。トランザクション・レベルの読取り一貫性によってリピータブル・リードが実現され、問合せで仮読取りが検索されなくなります。
読取り一貫性とUNDOセグメント
マルチバージョン読取り一貫性モデルを管理するには、表が同時に問合せおよび更新された場合に、読取り一貫性のある一連のデータがデータベースで作成される必要があります。
Oracle AI Databaseは、UNDOデータを使用して読取り一貫性を実現しています。
ユーザーがデータを変更すると、常にOracle AI DatabaseによってUNDOエントリが作成されます。UNDOエントリはUNDOセグメントに書き込まれます。UNDOセグメントには、未コミットのトランザクションや、最近コミットされたトランザクションによって変更されたデータの古い値が含まれています。このため、同じデータの異なる時点の複数のバージョンがデータベース内に存在することになります。データの読取り一貫性ビューを提供し、非ブロック化問合せを可能にするために、データベースでは異なる時点のデータのスナップショットを使用できます。
読取り一貫性は、単一のインスタンス内、およびOracle Real Application Clusters(Oracle RAC)環境内で保証されています。Oracle RACでは、データ・ブロックの読取り一貫性イメージをデータベース・インスタンス間で転送するために、キャッシュ・フュージョンと呼ばれるキャッシュ間ブロック転送メカニズムを使用します。
-
読取り一貫性: 例この例は、UNDOデータを使用して、コミットされた読取り分離レベルで文レベルの読取り一貫性を提供する問合せを示しています。
-
読取り一貫性とInterested Transaction Lists各セグメント・ブロックのブロック・ヘッダーにInterested Transaction list (ITL)が含まれています。
関連情報:
-
UNDO記憶域について学習するには、「UNDOセグメント」を参照してください
-
LOBに対する読取り一貫性のメカニズムについて学習するには、Oracle AI Database SecureFilesおよびラージ・オブジェクト開発者ガイドを参照してください。
読取り一貫性: 例
この例は、コミット読取り分離レベルで、UNDOデータを使用して文レベルの読取り一貫性を提供する問合せの例を示しています。
図1: コミット読取り分離レベルでの読取り一貫性

問合せによってデータ・ブロックを取得する場合、データベースによって、各ブロックのデータが問合せ開始時のブロックの内容を反映したものになることが保証されます。必要に応じて、ブロックに対する変更がロールバックされ、ブロックが問合せ処理の開始時点の内容に再構成されます。
データベースでは、SCNと呼ばれる内部順序付けメカニズムを使用することで、トランザクションの順序が保証されます。SELECT文が実行フェーズに移行すると、データベースによって、問合せの実行開始時点で記録されたSCNが特定されます。図12-1では、このSCNは10023です。問合せでは、SCN 10023に対応したコミット済データが戻されます。
図12-1では、10023より後のSCNを持つブロック(SCN 10024の2つのブロック)は変更済データであることが示されています。この場合、SELECT文では、コミット済の変更と一貫性があるバージョンのブロックが必要となります。データベースでは、現在のデータ・ブロックが新しいバッファにコピーされ、前のバージョンのブロックを再構築するためにUNDOデータが適用されます。このように再構築されたデータ・ブロックは、読取り一貫性(CR)クローンと呼ばれます。
図12-1では、データベースによって2つのCRクローンが作成されており、1つのブロックではSCN 10006との一貫性が保たれ、もう1つのブロックではSCN 10021との一貫性が保たれています。問合せに対しては、この再構築されたデータが戻されます。Oracle AI Databaseでは、このようにして内容を保証しない読取りが回避されています。
関連項目: 「データベース・バッファ・キャッシュ」および「システム変更番号(SCN)」
読取り一貫性とInterested Transaction List
各セグメント・ブロックのブロック・ヘッダーにinterested Transaction List (ITL)が含まれています。
データベースではITLを使用して、ブロックの変更が開始された時点でトランザクションがコミットされているかどうかが判断されます。
ITLのエントリは、ロックされた行のあるトランザクション、およびブロック内のコミット済の変更や未コミットの変更を含む行を表しています。ITLは、データベースに対する変更が行われたタイミングの情報を提供するUNDOセグメント内のトランザクション表を指しています。
ある意味では、ブロック・ヘッダーには、ブロック内の各行に影響を与えたトランザクションの最新の履歴が含まれていると考えられます。CREATE TABLE文およびALTER TABLE文のINITRANSパラメータは、保持するトランザクション履歴の量を制御します。
関連項目: INITRANSパラメータについて学習するには、Oracle AI Database SQL言語リファレンスを参照してください。
読取り一貫性および遅延挿入
遅延挿入という特殊な種類の挿入で、標準の読取り一貫性メカニズムは使用されません。
遅延挿入では、MEMOPTIMIZE_WRITEヒントを使用して、MEMOPTIMIZE FOR WRITEとして指定された表に挿入します。データベースではこれらの挿入を、バッファ・キャッシュではなくラージ・プールでバッファします。データベースでは、REDOおよびUNDOを使用して変更を追跡することはありません。かわりに、領域管理コーディネータ(SMCO)によってバッファがディスクに書き込まれると、データベースによって変更が自動的にコミットされます。この変更はロールバックできません。
遅延挿入は、次の重要な点で従来の挿入とは異なります。
-
アプリケーションではコミット済となっている、ラージ・プールに存在するデータが失われる可能性があります。たとえば、変更が保存されたことがアプリケーションにより報告された場合でも、変更がディスクに保存される前にデータベース・インスタンスが失敗する場合があります。
-
メモリーから直接データを読み取ることはできません。ライターは、バックグラウンド・プロセスが変更をディスクに書き込むまで、自身の変更を読み取ることができません。読取り側は、コミットされた変更がディスクに書き込まれるまでその変更を参照できません。
データ消失を回避する必要があるクライアント・アプリケーションでは、ラージ・プールへの書込み後にデータのローカル・コピーを保持する必要があります。クライアントはDBMS_MEMOPTIMIZEパッケージを使用してメモリーへの書込みの永続性を追跡し、DBMS_MEMOPTIMIZE_ADMINパッケージを使用してデータベースを強制的にディスクに書き込むことができます。
関連情報:
-
MEMOPTIMIZE FOR WRITEヒントについてさらに学習するには、『Oracle AI Database SQL言語リファレンス』を参照してください。
ロックのメカニズム
一般に、マルチユーザー・データベースでは、なんらかのデータ・ロックを使用してデータの同時実行性、一貫性、および整合性の問題を解決します。
ロックは、同じリソースにアクセスするトランザクション間で、破壊的な相互作用が出現しないようにするメカニズムです。
関連項目: 「Oracle AI Databaseのロック・メカニズムの概要」
ANSI/ISOトランザクション分離レベル
ANSIとISO/IECの両方で採用されているSQL規格では、トランザクション分離レベルが4つ定義されています。これらのレベルは、トランザクション処理のスループットに与える影響の度合いが異なります。
これらの分離レベルは、複数のトランザクションを同時に実行するときに防ぐ必要がある現象という観点から定義されています。回避可能な現象とは、次のものです。
-
ダーティ・リード
未コミットのトランザクションが書き込んだデータを、別のトランザクションが読み取る現象。
-
非リピータブル・リード(ファジー読取り)
あるトランザクションが以前に読み取ったデータをもう一度読み取ったときに、コミットされた別のトランザクションによってそのデータが変更または削除されたことが明らかになる現象。たとえば、ユーザーがデータに変更があるかどうかを知るためにのみ、ある行を問い合せ、後で再度同じ行を問い合せるという現象などのことです。
-
仮読取り
あるトランザクションが検索条件を満たす一連の行を戻す問合せを2回実行する間に、コミットされた別のトランザクションによってその条件を満たす新しい行が挿入されたことが明らかになる現象。
たとえば、トランザクションから従業員数を問い合せるとします。5分後に同じ問合せを実行したところ、他のユーザーが新規採用者のレコードを挿入したため、戻される従業員数は1人増えています。問合せ基準を満たすデータは増えていますが、ファジー読取りとは異なり、すでに読み取ったデータは変更されていません。
SQL規格では、特定の分離レベルで実行されるトランザクションで起こり得ることという観点で4つの分離レベルを定義しています。表12-1に、これらのレベルを示します。
表1分離レベル別による回避可能な読取り現象
| 分離レベル | ダーティ・リード | 非リピータブル・リード | 仮読取り |
|---|---|---|---|
| 未コミットの読取り | 可能 | 可能 | 可能 |
| 読取りがコミットされました | 不可能 | 可能 | 可能 |
| 反復可能読取り | 不可能 | 不可能 | 可能 |
| シリアル化可能 | 不可能 | 不可能 | 不可能 |
Oracle AI Databaseには、コミット読取り(デフォルト)およびシリアライズ可能の分離レベルがあります。また、読取り専用モードも提供されています。
関連情報:
-
コミット読取り、シリアライズ可能および読取り専用の分離レベルについて学習するには、「Oracle AI Databaseのトランザクション分離レベルの概要」を参照してください
-
SQL標準へのOracle AI Databaseの準拠については、『Oracle AI Database SQL言語リファレンス』を参照してください。
Oracle AI Databaseのトランザクション分離レベルの概要
トランザクション分離レベルのANSI規格は、各分離レベルで許可または防止される現象という観点から定義されています。
Oracle AI Databaseでは、トランザクション分離レベルが提供されています。
-
コミット読取り分離レベル コミット読取り分離レベルで、トランザクションによって実行される問合せで、トランザクション開始後ではなく、問合せ終了前にコミット済のデータのみが表示されます。
-
シリアライズ可能分離レベルシリアライズ可能分離レベルでは、問合せの開始時ではなく、トランザクション終了時にコミット済の変更およびこのトランザクション自体が行った変更のみを参照することができます。
-
読取り専用分離レベル読取り専用分離レベルはシリアライズ可能分離レベルと類似していますが、読取り専用トランザクションでは、
SYSユーザー以外はトランザクションでデータを変更できません。
関連情報:
-
トランザクション分離レベルについてさらに学習するには、Oracle AI Database開発ガイドを参照してください。
-
SET TRANSACTION ISOLATION LEVELについて学習するには、Oracle AI Database SQL言語リファレンスおよび『Oracle AI Database PL/SQL言語リファレンス』を参照してください。
コミット読取り分離レベル
コミット読取り分離レベルで、トランザクションによって実行される問合せにおいて、トランザクション開始の前ではなく、問合せ終了前にコミット済のデータのみが表示されます。
この分離レベルがデフォルトになります。これはトランザクションの競合がほとんど発生しないデータベース環境に適しています。
コミット読取りトランザクション内の問合せでは、問合せ処理中にコミットされるデータは読み取られません。たとえば、100万行を持つ表の問合せ中に、別のトランザクションによって行950,000への更新がコミットされたとすると、この問合せで行950,000を読み取っても、その変更は反映されていません。ただし、問合せによって読み取られたデータを他のトランザクションに変更することはできないため、他のトランザクションは問合せ実行の間にデータが変更される可能性があります。このため、同じ問合せを2回実行するトランザクションでは、ファジー読取りと仮読取りが発生する可能性があります。
-
コミット読取り分離レベルでの読取り一貫性データベースでは、ユーザーが何 もしなくても、あらゆる問合せに対して一貫した結果セット が保証され、データ整合性は保証されます。
-
コミット読取りトランザクションの書込みの競合コミット読取りトランザクションの競合する書込みは、コミットされていない同時実行トランザクションによって更新された行の変更をトランザクションが試みるときに発生します。
コミット読取り分離レベルでの読取り一貫性
データベースでは、ユーザーが何もしなくても、あらゆる問合せに対して一貫した結果セットが保証され、データ整合性が保証されます。
UPDATE文のWHERE句などで使用される暗黙的問合せでは、一貫した結果セットが保証されます。ただし、暗黙的問合せ内の各文では、そのDML文自体によって行われた変更は参照されず、変更前に存在したデータが参照されます。
SELECT文のリストにPL/SQLファンクションが含まれる場合、親SQLレベルではなくPL/SQLファンクション・コード内で実行されるSQL文のレベルにおいて、文レベルの読取り一貫性が適用されます。たとえば、ファンクションは、別のユーザーがデータを変更およびコミットした表にアクセスする場合があります。ファンクション内のSELECTの実行ごとに、読取り一貫性を備えた新しいスナップショットが設定されます。
関連項目: 「副問合せ」
コミット読取りトランザクション内での書込みの競合
コミット読取りトランザクションでは、トランザクションがコミットされていない同時トランザクションによって更新された行を変更しようとすると、競合する書込みが実行されます。
行の変更を防止するトランザクションは、ブロックしているトランザクションと呼ばれる場合があります。コミット読取りトランザクションは、ブロックしているトランザクションが終了して行ロックが解除されるまで待機します。
オプションは次のとおりです:
-
ブロックしているトランザクションがロールバックされた場合、待機しているトランザクションでは、ブロックしているトランザクションが存在していなかったかのように、ロックされていた行が変更されます。
-
ブロックしているトランザクションがコミットされてロックが解除された場合、待機しているトランザクションでは、新たに変更された行に対して更新が実行されます。
次の表に、トランザクション1 (シリアライズ可能トランザクションまたはコミット読取りトランザクション)とコミット読取りトランザクション2との間の相互作用を示します。これは、更新の消失と呼ばれるような典型的な状況を示しています。トランザクション1による更新内容は、トランザクション1がコミットしても表にはありません。このような更新内容の消失の問題をいかに回避するかは、アプリケーション開発の重要な点です。
表2 READ COMMITTEDトランザクションにおける書込みと更新内容が消失する
| セッション 1 | セッション 2 | 説明 |
|---|---|---|
SQL> SELECT last_name,
salary FROM employees
WHERE last_name IN
('Banda', 'Greene',
'Hintz');
LAST_NAME SALARY
------------- ----------
Banda 6200
Greene 9500 |
アクションはありません。 | セッション1で、Banda、GreeneおよびHintzの給与を問い合せます。Hintzという名前の従業員が見つかりません。 |
SQL> UPDATE employees SET salary = 7000 WHERE last_name = 'Banda'; |
アクションはありません。 | セッション1で、Bandaの給与を更新することによってトランザクションを開始します。トランザクション1のデフォルトの分離レベルは、READ COMMITTEDです。 |
| アクションはありません。 | SQL> SET TRANSACTION ISOLATION LEVEL READ COMMITTED; |
セッション2でトランザクション2を開始して、分離レベルを明示的にREAD COMMITTEDに設定します。 |
| アクションはありません。 | SQL> SELECT last_name,
salary FROM employees
WHERE last_name IN
('Banda', 'Greene',
'Hintz');
LAST_NAME SALARY
------------- ----------
Banda 6200
Greene 9500 |
トランザクション2で、Banda、GreeneおよびHintzの給与を問い合せます。Oracle AI Databaseでは読取り一貫性が使用され、トランザクション1によって行われた未コミットの更新前のBandaの給与を表示します。 |
| アクションはありません。 | SQL> UPDATE employees SET salary = 9900 WHERE last_name='Greene'; |
トランザクション1ではBandaの行のみがロックされているため、トランザクション2でGreeneの給与が正常に更新されます。 |
SQL> INSERT INTO employees (employee_id, last_name, email, hire_date, job_id) VALUES (210, 'Hintz', 'JHINTZ', SYSDATE, 'SH_CLERK'); |
アクションはありません。 | トランザクション1で、従業員Hintzの行を挿入しますが、コミットはしません。 |
| アクションはありません。 | SQL> SELECT last_name,
salary FROM employees
WHERE last_name IN
('Banda', 'Greene',
'Hintz');
LAST_NAME SALARY
------------- ----------
Banda 6200
Greene 9900 |
トランザクション2で、従業員Banda、GreeneおよびHintzの給与を問い合せます。 トランザクション2では、このトランザクション自体で更新したGreeneの給与を参照できます。トランザクション2では、トランザクション1によって行われた未コミットのBandaの給与の更新やHintzの挿入は表示されません。 |
| アクションはありません。 | SQL> UPDATE employees SET salary = 6300 WHERE last_name = 'Banda'; -- prompt does not return |
トランザクション2で、現在トランザクション1によってロックされているBandaの行の更新を試行したため、書込みの競合が発生します。トランザクション2は、トランザクション1の終了を待機します。 |
SQL> COMMIT; |
アクションはありません。 | トランザクション1では作業をコミットし、トランザクションを終了します。 |
| アクションはありません。 | 1 row updated. SQL> |
Bandaの行に対するロックが解除されたため、トランザクション2ではBandaの給与が更新されています。 |
| アクションはありません。 | SQL> SELECT last_name,
salary FROM employees
WHERE last_name IN
('Banda', 'Greene',
'Hintz');
LAST_NAME SALARY
------------- ----------
Banda 6300
Greene 9900
Hintz |
トランザクション2で、従業員Banda、GreeneおよびHintzの給与を問い合せます。トランザクション1によってコミットされたHintzの挿入がトランザクション2でも参照可能になりました。トランザクション2では、このトランザクション自体で行ったBandaの給与への更新が表示されます。 |
| アクションはありません。 | COMMIT; |
トランザクション2では作業をコミットし、トランザクションを終了します。 |
SQL> SELECT last_name,
salary FROM employees
WHERE last_name IN
('Banda', 'Greene',
'Hintz');
LAST_NAME SALARY
------------- ----------
Banda 6300
Greene 9900
Hintz |
アクションはありません。 | セッション1で、Banda、GreeneおよびHintzの行を問い合せます。Bandaの給与は6300ですが、これはトランザクション2で更新された値です。トランザクション1でBandaの給与を7000に更新しましたが、この更新内容は消失しました。 |
関連情報:
-
更新の消失について学習するには、「ロックの使用」を参照
-
データベースによる行ロックの取得時期と理由を学習するには、「行ロック(TX)」
シリアライズ可能分離レベル
シリアライズ可能分離レベルでは、問合せの開始時ではなく、トランザクションの開始時にコミット済の変更およびこのトランザクション自体が行った変更のみを参照できる。
シリアライズ可能トランザクションは、他のユーザーがデータベースのデータを変更していないように見える環境内で動作します。シリアライズ可能な分離は、次のような環境に適しています。
-
大規模データベースを使用し、短いトランザクションでごく少数の行しか更新しない環境。
-
2つの同時実行トランザクションが同一の行を更新するようなことが比較的少ない環境。
-
比較的長時間にわたって実行されるトランザクションが主に読取り専用である環境。
シリアライズ可能分離では、通常は文レベルで確保される読取り一貫性が、トランザクション全体に拡張されます。トランザクションによって読み取られるすべての行は、再度読み取っても同じであることが保証されます。トランザクション実行中は、問合せによって戻される結果が同じであることが保証されるため、トランザクションの実行時間に関係なく、他のトランザクションによる変更は問合せで参照できません。シリアライズ可能トランザクションでは、内容を保証しない読取り、ファジー読取りまたは仮読取りの現象は発生しません。
Oracle AI Databaseの場合、シリアライズ可能なトランザクションでは、他のトランザクションで行が変更され、シリアライズ可能なトランザクションが開始されたときにすでにコミットされている行のみ変更できます。シリアライズ可能トランザクションが、その開始後にコミットされた別のトランザクションによって変更されたデータの更新または削除を試行すると、データベースでは次のようなエラーが生成されます。
ORA-08177: Cannot serialize access for this transaction
シリアライズ可能トランザクションでORA-08177エラーが発生した場合、アプリケーションでは次のいずれかのアクションを実行できます。
-
実行された作業をそのポイントまでコミットします
-
追加の(異なる)文を実行します(トランザクション内で以前に設定したセーブポイントまでロールバックした後など)。
-
トランザクション全体をロールバックします。
次の表に、シリアライズ可能トランザクションと他のトランザクションとの間の相互作用を示します。シリアライズ可能トランザクションにおいては、シリアライズ可能トランザクションの開始後に他のトランザクションでコミットされた行の変更を試行しなければ、シリアライズ・アクセスの問題を回避できます。
表3シリアライズ可能トランザクション
| セッション 1 | セッション 2 | 説明 |
|---|---|---|
|
アクションはありません。 | セッション1で、Banda、GreeneおよびHintzの給与を問い合せます。Hintzという名前の従業員が見つかりません。 |
|
アクションはありません。 | セッション1で、Bandaの給与を更新することによってトランザクション1を開始します。デフォルトの分離レベルはREAD COMMITTEDです。 |
| アクションはありません。 | |
セッション2でトランザクション2を開始して、SERIALIZABLE分離レベルに設定します。 |
| アクションはありません。 | |
トランザクション2で、Banda、GreeneおよびHintzの給与を問い合せます。Oracle AI Databaseでは読取り一貫性が使用され、トランザクション1によって行われた未コミットの更新前のBandaの給与を表示します。 |
| アクションはありません。 | |
Bandaの行のみがロックされているため、トランザクション2でGreeneの給与は正常に更新されます。 |
|
アクションはありません。 | トランザクション1で、従業員Hintzの行を挿入します。 |
|
アクションはありません。 | トランザクション1では作業をコミットし、トランザクションを終了します。 |
|
|
セッション1で従業員Banda、GreeneおよびHintzの給与を問い合せると、トランザクション1によってコミットされた変更が表示されます。セッション1では、トランザクション2での未コミットのGreeneの更新は参照できません。 トランザクション2で、従業員Banda、GreeneおよびHintzの給与を問い合せます。Oracle AI Databaseの読取り一貫性により、トランザクション1でコミットされたHintzの挿入およびBandaの更新は、トランザクション2では表示されない。トランザクション2では、このトランザクション自体で行ったGreeneの給与への更新が表示されます。 |
| アクションはありません。 | |
トランザクション2では作業をコミットし、トランザクションを終了します。 |
|
|
両方のセッションで、Banda、GreeneおよびHintzの給与を問い合せます。各セッションで、トランザクション1およびトランザクション2で行われたすべてのコミット済の変更を参照できます。 |
|
アクションはありません。 | セッション1で、Hintzの給与を更新することによってトランザクション3を開始します。トランザクション3のデフォルトの分離レベルは、READ COMMITTEDです。 |
| アクションはありません。 | |
セッション2でトランザクション4を開始して、SERIALIZABLE分離レベルに設定します。 |
| アクションはありません。 | |
トランザクション4で、Hintzの給与の更新を試みますが、トランザクション3でHintzの行がロックされているためにブロックされます。トランザクション4は、トランザクション3の後のキューに入ります。 |
|
アクションはありません。 | トランザクション3でHintzの給与の更新をコミットして、トランザクションを終了します。 |
| アクションはありません。 | |
コミットしてトランザクション3を終了することによって、トランザクション4におけるHintzの更新がORA-08177エラーが発生して失敗します。この問題は、トランザクション3がトランザクション4が開始した後にヒント更新をコミットしたために発生します。 |
| アクションはありません。 | |
セッション2で、トランザクション4をロールバックして終了します。 |
| アクションはありません。 | |
セッション2でトランザクション5を開始して、SERIALIZABLE分離レベルに設定します。 |
| アクションはありません。 | |
トランザクション5で、Banda、GreeneおよびHintzの給与を問い合せます。トランザクション3によってコミットされたHintzの給与の更新を参照できます。 |
| アクションはありません。 | |
トランザクション5で、Hintzの給与を異なる値に更新します。トランザクション5が開始される前にトランザクション3でのHintzの更新をコミットしているため、シリアライズ・アクセスの問題は回避されます。 ノート: トランザクション5が開始された後に、別のトランザクションでHintzの行を更新してコミットした場合は、再度シリアライズ・アクセスの問題が発生します。 |
| アクションはありません。 | |
セッション2で、問題なく更新をコミットして、トランザクションを終了します。 |
関連情報:
読取り専用分離レベル
読取り専用分離レベルはシリアライズ可能分離レベルと類似していますが、読取り専用トランザクションでは、SYSユーザー以外はトランザクションでデータを変更できません。
読取り専用トランザクションでは、ORA-08177エラーは発生しません。読取り専用トランザクションは、トランザクション開始時点での一貫性を保たれる必要があるレポートの生成に役立ちます。
Oracle AI Databaseでは、必要に応じてUNDOセグメントからデータを再構築することによって、読取り一貫性を実現しています。UNDOセグメントは循環方式で使用されるため、データベースではUNDOデータを上書きできます。長時間実行されるレポートでは、読取り一貫性を保つために必要なUNDOデータが他のトランザクションによって再利用され、snapshot too oldというエラーが発生することがあります。UNDO保存期間とは、古いUNDOデータを上書きせずに保存する最低期間を設定することで、この問題を適切に回避します。
関連情報:
-
UNDO保存期間の設定方法を学習するには、『Oracle AI Database管理者ガイド』を参照
Oracle AI Databaseのロック・メカニズムの概要
ロックは破壊的な相互作用が起きないようにするメカニズムである。
共有データにアクセスする複数のトランザクション間で不正確なデータの更新または基礎となるデータ構造の不正な変更を引き起こす場合に、相互作用は破壊的になります。ロックは、データベースの同時実行性および一貫性を維持するために非常に重要です。
-
ロック動作の概要データベースでは、ロックを取得した操作に応じて、複数のタイプのロックが保持されます。
-
ロックの使用シングルユーザーのデータベースでは、情報を変更するのが1人のユーザーのみであるため、ロックは必要ありません。ただし、複数のユーザーがデータにアクセスして変更する場合、データベースには、同じデータに対する同時変更を防止する手段が必要です。
-
ロック・モード Oracle AI Databaseでは、最高水準のデータ同時実行可能性を実現しながらフェイルセーフなデータ整合性も維持するため、自動的に、可能な限り低い制限レベルが自動的に使用されます。
-
ロック変換とエスカレーションOracle AI Databaseでは、必要なロック変換が実行されます。
-
ロックの期間 Oracle AI Databaseでは、なんらかのイベントが発生すると、トランザクションがそのリソースを必要としなくなるように、ロックが自動的に解放されます。
-
ロックとデッドロックデッドロックとは、2人以上のユーザーが、相手がロックされているデータをお互いに待機している状況です。デッドロックが発生すると、トランザクションは続行されません。
ロック動作の概要
データベースでは、ロックを取得する操作に応じて、複数のタイプのロックが使用されます。
一般に、データベースでは、排他ロックと共有ロックの2種類のロックが使用されます。排他ロックは、1つのリソース(行や表など)に対して1つのみ取得でき、共有ロックは、1つのリソースに対して複数取得できます。
ロックは、読取り側と書込み側の相互作用に影響を与えます。読取り側はリソースの問合せで、書込み側はリソースを変更する文です。次に、Oracle AI Databaseにおける、リーダーおよびライターに対するロック動作の概要を示します。
-
行は、書込み側によって変更される場合にのみロックされます。
文がある行を更新する場合、そのトランザクションはその行に対してのみロックを取得します。行レベルで表データをロックすることによって、同一のデータに対する競合が最小限に抑えられます。通常の状況では、脚注1行ロックはブロック・レベルや表レベルに拡大されません。
-
行の書込み側は、同じ行に対する同時書込みをブロックします。
あるトランザクションで行を変更している場合は、行ロックによって、他のトランザクションからの同じ行に対する同時変更が防止されます。
-
読取り側が書込み側をブロックすることはありません。
行の読取り側は行をロックしないため、書込み側はこの行を変更できます。唯一の例外は
SELECT ... FOR UPDATE文で、この文がSELECT文の特殊なタイプであり、読取り中の行をロックします。 -
書込み側が読取り側をブロックすることはありません。
行が書込み側によって変更されている場合、データベースでは、UNDOデータを使用して読込み側に一貫性のある行のビューが表示されます。
ノート:保留中の分散トランザクションでは、非常に特殊な状況で、同じデータ・ブロックの書込みの待機が必要となる場合があります。
関連情報:
-
SELECT ... FOR UPDATEについて学習するには、『Oracle AI Database SQL言語リファレンス』を参照 -
インダウト分散トランザクションに関連する待機について学習するには、『Oracle AI Database管理者ガイド』を参照
ロックの使用
シングル・ユーザーのデータベースでは、情報を変更するのは1人のユーザーのみであるため、ロックは必要ありません。ただし、複数のユーザーがデータにアクセスして変更する場合、データベースには、同じデータに対する同時変更を防止する手段が必要です。
ロックによって、次のようなデータベースの重要な要件を満たすことが可能になります:
-
一貫性
あるセッションが表示または変更しているデータは、そのユーザーがデータの使用を終了するまで他のセッションでは変更できません。
-
完全性
データおよび構造には、すべての変更内容が適切な順序で反映される必要があります。
Oracle AI Databaseでは、ロック・メカニズムを使用して、トランザクション間のデータの同時実行性、一貫性および整合性を確保します。ロックは自動的に実行されるため、ユーザーの操作は必要ありません。
ロックの必要性については、単一の行に対する同時更新で説明できます。次の例では、単純なWebベースのアプリケーションによって、エンド・ユーザーに対して従業員の電子メールおよび電話番号が表示されます。アプリケーションでは、次のようなUPDATE文を使用してデータが変更されます。
UPDATE employees
SET email = ?, phone_number = ?
WHERE employee_id = ?
AND email = ?
AND phone_number = ?
この例のUPDATE文では、WHERE句中の電子メールと電話番号は、特定の従業員に関する変更前の元の値になります。この更新では、アプリケーションで変更される行は、最後に読み取られ、ユーザーに表示された後、変更されていないことが保証されます。このようにして、アプリケーションでは、あるユーザーによって行われた変更を他のユーザーが上書きして更新内容が消失する、更新内容の消失の問題が回避されます(更新内容の消失の例は、表12-2を参照)。表12-4に、2つのセッションがほぼ同時にemployees表の同じ行の変更を試行した場合の一連のイベントを示します。
表4行ロックの例
| T | セッション 1 | セッション 2 | 摘要 |
|---|---|---|---|
| t0 | |
セッション1で、hr1ユーザーがhr.employeesのHimuroのレコードを問い合せて、employee_id(118)、email(GHIMURO)およびphone_number(515.127.4565)属性を表示します。 |
|
| t1 | |
セッション2で、hr2ユーザーがhr.employeesのHimuroのレコードを問い合せて、employee_id(118)、email(GHIMURO)およびphone_number(515.127.4565)属性を表示します。 |
|
| t2 | |
セッション1で、hr1ユーザーがその行の電話番号を515.555.1234に更新します。この場合、GHIMUROの行に対してロックを取得します。 |
|
| t3 | |
セッション2で、
|
|
| t4 | |
セッション1で、 このコミットによってHimuroに対する変更が確定され、待機しているセッション2のブロックが解除されます。 |
|
| t5 | |
セッション2で、 条件が一致しないため、セッション2ではレコードが更新されません。 |
|
| t6 | |
セッション1で、hr1ユーザーは、GHIMUROの行を誤った電話番号で更新したことに気付きます。そのためユーザーは新たにトランザクションを開始して、この行の電話番号を515.555.1235に更新します。これによりGHIMUROの行がロックされます。 |
|
| t7 | |
セッション2で、hr2ユーザーは、hr.employeesのHimuroのレコードを問い合せます。レコードには、t4でセッション1によってコミットされた電話番号の更新内容が表示されます。Oracle AI Databaseの読取り一貫性によって、セッション2ではt6の未コミットの変更は表示されません。 |
|
| t8 | |
セッション2で、hr2ユーザーが同じ行を更新しようとしますが、現在hr1が行を処理中のためブロックされます。 |
|
| t9 | |
セッション1で、hr1ユーザーがトランザクションをロールバックして終了します。 |
|
| t10 | |
セッション1による更新がロールバックされたため、セッション2による電話番号の更新は成功します。GHIMUROの行が条件に一致するため、更新は成功します。 |
|
| t11 | |
セッション2で、更新をコミットして、トランザクションを終了します。 |
Oracle AI Databaseでは、SQL文を実行するときに、必要なロックを自動的に取得します。たとえば、セッションによるデータの変更が許可される前に、最初にデータをロックする必要があります。ロックによってセッションは更新対象データに対する排他制御を取得するため、ロックが解除されるまでは他のトランザクションはロックされたデータを変更できません。
Oracle AI Databaseのロック・メカニズムはトランザクション制御と密接に結び付けられているため、アプリケーション設計者はトランザクションを適切に定義する必要があるのみで、ロックはOracle AI Databaseによって自動的に管理されます。ユーザーはリソースを明示的にロックする必要はありませんが、Oracle AI Databaseにはユーザーが手動でデータをロックするための方法も用意されています。
次の項では、Oracle AI Databaseでデータの同時実行性が実現される方法を理解するための重要な概念を説明します。
関連項目: 更新内容の消失防止に役立つサブプログラムを含むOWA_OPT_LOCKパッケージについて学習するには、Oracle AI Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンスを参照してください
ロックモード
Oracle AI Databaseでは、最高水準のデータ同時実行可能性を実現しながらフェイルセーフなデータの整合性を確保するために、可能な限り低い制限レベルが自動的に使用されます。
制限レベルが低いほど、他のユーザーによるデータへのアクセスがより容易になります。逆に、制限レベルが高いほど、他のトランザクションで取得できるロックのタイプがより制限されます。
Oracle AI Databaseでは、マルチユーザー・データベースで2つのロック・モードを使用します。
-
排他ロック・モード
このモードは、関連リソースの共有を防止します。トランザクションでは、データを変更するときに排他ロックを取得します。リソースを排他的にロックした最初のトランザクションは、その排他ロックが解除されるまで、そのリソースを変更できる唯一のトランザクションになります。
-
共有ロック・モード
このモードでは、操作の種類に応じて、関連するリソースの共有が可能です。データを読み取る複数のユーザーはそのデータを共有でき、またそれぞれがシェアロックを保持することによって、エクスクルーシブロックを必要とする書き込みユーザーの同時アクセスを防ぎます。複数のトランザクションが同じリソースについて共有ロックを取得できます。
あるトランザクションで、SELECT ... FOR UPDATE文を使用して単一の表の行を選択するとします。このトランザクションでは、排他行ロックおよび行共有表ロックを取得します。行ロックでは、その他のセッションは、ロックされた行以外の任意の行を変更できますが、表ロックでは、セッションによる表の構造の変更が禁止されています。したがって、データベースでは、任意の数の文を実行できます。
ロック変換とロックの段階的拡大
Oracle AI Databaseでは、必要な場合にロック変換が実行されます。
ロックへの変換では、データベースによって、低い制限の表のロックが、より高い制限の1つに自動的に変換されます。たとえば、あるトランザクションで特定の従業員に対するSELECT ... FOR UPDATEを発行し、その後ロックされた行を更新すると仮定します。この場合、データベースでは、行共有表ロックが行排他表ロックに自動的に変換されます。トランザクションは、トランザクション内で挿入、更新または削除の対象になる行すべてに対して排他ロックを保持します。行ロックは、制限の最も高い程度で取得されるため、ロック変換はまったく必要なく、実行されません。
ロック変換は、あるレベル(行レベルなど)、1つのレベルで多数のロック解除が保持され、データベースがより高いレベルの粒度(表レベルなど)にランクを上げると発生する11とは異なります。あるセッションが表の中の多数の行をロックした場合、データベースによっては、行ロックが単一の表ロックに自動的に拡大される場合があります。ロックの数は少なくなりますが、ロックされている対象の制限は大きくなります。
Oracle AI Databaseでは、ロックがエスカレーションされることはありません。 ロックの段階的拡大はデッドロックの可能性を大幅に増します。たとえば、システムがトランザクション1のためにロックの拡大を試行しますが、トランザクション2によって保持されているロックのために拡大できないとします。トランザクション2の処理を続行するために同じデータのロックの段階的拡大が必要な場合、デッドロックが発生します。
時間のロック
Oracle AI Databaseでは、なんらかのイベントが発生すると、トランザクションがそのリソースを必要としなくなるように、ロックが自動的に解放されます。
通常、トランザクション内の文で取得したロックは、トランザクションの存続期間中保持されます。これらのロックは、同時トランザクションによって内容を保証しない読取り、更新の内容の消失、有害なDDLなどの損傷を招く干渉を防止します。ノート:索引付けされていない外部キーは、トランザクションではなく、文の存続期間中保持されるため、子表に対して実行される表ロック。また、DBMS_LOCKパッケージを使用すると、ユーザー定義のロックを自由に割当ておよび解除でき、トランザクションの境界を越えて保持することもできます。
Oracle AI Databaseでは、トランザクションをコミットまたはロールバックすると、そのトランザクション内の文で取得したすべてのロックが解除します。また、Oracle AI Databaseは、セーブポイントまでロールバックすると、セーブポイントより後で取得されたロックも解除します。ただし、ロックを解除されて使用可能となったリソースに対してロックを取得できるのは、ロック中だったリソースを待機していなかったトランザクションのみです。ロック中のリソースを待機していたトランザクションは、元のトランザクションが完全にコミットまたはロールバックされるまで待機し続けます。
関連情報:
-
トランザクションを待機する動作を示す表13-3を参照
-
DBMS_LOCKについてさらに学習するには、「ユーザー定義ロックの概要」を参照してください
ロックおよびデッドロック
デッドロックとは、2人以上のユーザーが、相手がロックされているデータをお互いに待機している状況を指すものです。デッドロックが発生すると、トランザクションは続行されません。
Oracle AI Databaseでは、デッドロックを自動的に検出し、デッドロックに関係している文の一方をロールバックし、競合する一連の行ロックを解放することにより、デッドブロックを自動で解決します。また、データベースでは、文レベルのロールバックが行われたトランザクションに対して対応するメッセージが戻されます。ロールバックされる文は、デッドロックが検出されたトランザクションに属しています。通常、通知されたトランザクションは明示的にロールバックする必要がありますが、待機した後でロールバック文を再試行できます。表12-5に、デッドロック状態の2つのトランザクションを示します。
表5デッドロック・トランザクション
| T | セッション 1 | セッション 2 | 説明 |
|---|---|---|---|
| t0 | |
|
セッション1でトランザクション1を開始して、従業員100の給与を更新します。セッション2でトランザクション2を開始して、従業員200の給与を更新します。各トランザクションでは、そのトランザクションで更新する行のみがロックされるため、問題は発生しません。 |
| t1 | |
|
トランザクション1で、現在トランザクション2でロックされている従業員200の行の更新を試行します。トランザクション2で、現在トランザクション1でロックされている従業員100の行の更新を試行します。 どちらのトランザクションでも、処理を続行または終了するために必要なリソースを取得できないため、デッドロックが発生します。各トランザクションがいくら待機しても、競合するロックは保持されたままです。 |
| t2 | |
トランザクション1でデッドロックが検出されて、t1で発行された ノート: デッドロック状態になっているセッションのうちの一方のみが実際にデッドロック・エラーを受信しますが、どちらのセッションもエラーになる可能性があります。 |
|
| t3 | |
セッション1で、t0で行った更新をコミットして、トランザクション1を終了します。t1で正常に行われなかった更新はコミットされません。 | |
| t4 | |
トランザクション1によってブロックされていた、t1でのトランザクション2による更新が実行されます。プロンプトが戻されます。 | |
| t5 | |
セッション2で、t0およびt1において行った更新をコミットして、トランザクション2を終了します。 |
ほとんどの場合、デッドロックは、トランザクションがOracle AI Databaseのデフォルト・ロックを明示的にオーバーライドした場合に発生します。Oracle AI Databaseではロックの段階的拡大は実行されず、問合せでの読取りロックは使用されませんが、行レベルのロッキング(ページ・レベルのロッキングではありません)のみが使用されるため、デッドロックがほとんど起こらない。
関連情報:
-
明示的に表をロックしたときのデッドロックの処理方法を学習するには、Oracle AI Database開発ガイドを参照してください。
自動ロックの概要
Oracle AI Databaseのトランザクションは、トランザクションのかわりにリソースを自動的にロックして、同じリソースへの排他的アクセスを必要とする処理を他のトランザクションで実行しないようにします。
データベースは、リソースおよび実行される操作に応じて、様々な制限レベルの様々なタイプのロックを自動的に取得します。ノート:単純な読取り時に行がロックされることはありません。
Oracle AI Databaseのロックは、次の表に示すカテゴリに分類されます。
表6ロックのカテゴリ
| ロック | 摘要 | 詳細を表示するには |
|---|---|---|
| DMLロック | データを保護します。たとえば、表ロックは表全体をロックし、行ロックは選択された行をロックします。 | DMLロック |
| DDLロック | スキーマ・オブジェクトの構造、たとえば表とビューのディクショナリ定義を保護します。 | 「DDLロック」 |
| システム・ロック | データファイルなどの内部データベース構造を保護します。ラッチ、mutexおよび内部ロックは完全に自動的です。 | 「システム・ロック」 |
-
DMLロック DMLロックは、データ・ロックとも呼ばれて、複数のユーザーが同時にアクセスされるデータの整合性を保証します。
-
DDLロックデータ・ディクショナリ(DDL)ロックによって、進行中のDDL操作によってオブジェクトの処理中または参照中に、そのオブジェクトの定義は保護されます。
-
システム・ロック Oracle AI Databaseでは、様々なタイプのシステム・ロックを使用して、内部データベースおよびメモリー構造を保護します。ユーザーは、システム・ロックの出現や継続期間を制御できないため、このメカニズムにはアクセスできません。
DMLロック
DMLロックは、データ・ロックとも呼ばれているため、複数のユーザーが同時にアクセスするデータの整合性を保証します。
たとえば、DMLロックでは、オンライン・ブック・ショップで在庫が残り1冊となった本を2人の顧客が購入してしまうことを防止します。DMLロックにより、競合するDMLまたはDDL操作を同時に行うことによる破壊的な干渉を防ぎます。
DML文では、次のタイプのロックを自動的に取得します。
次の各項では、各タイプのロックまたはロック・モードの後のカッコ内にある頭字語の略語は、Oracle Enterprise Manager(Enterprise Manager)のロック・モニターで使用される略語です。Enterprise Managerでは、表ロックのモード(RSやSRXなど)が示されるかわりに、すべての表ロックにTMと表示される可能性があります。
-
行ロック(TX)行ロック(TXロックとも呼ばれる)は、表の1つの行に対するロックである。トランザクションでは、
INSERT、UPDATE、DELETE、MERGEまたはSELECT... FORUPDATE文によって変更される各行での行ロックを取得します。行ロックは、トランザクションがコミットまたはロールバックされるまで存在します。 -
表ロック(TM) 表ロック(TMロックとも呼ばれる)は、表が
INSERT、UPDATE、DELETE、MERGE、FOR UPDATE句を含むSELECTまたはLOCK TABLE文によって変更されると、トランザクションによって取得されます。 -
ロックと外部鍵 Oracle AI Databaseでは、親キーとそれによって依存する外部鍵との関連において、親キーの同時実行性制御を最大化できます。
行ロック(TX)
行ロック(TXロックとも呼ばれる)は、表の単一の行に対するロックです。トランザクションでは、INSERT、UPDATE、DELETE、MERGEまたはSELECT ... FOR UPDATE文によって変更される各行での行ロックを取得します。行ロックは、トランザクションがコミットまたはロールバックされるまで存在します。
行ロックは、主に2つのトランザクションによる同じ行の変更を防止するためのキューイング・メカニズムとして機能します。変更される行は常に排他モードでロックされるため、ロックを保持しているトランザクションがコミットまたはロールバックされるまで、他のトランザクションはその行を変更できません。行ロックでは、最もきめの細かいロックが実現されるため、最高の同時実行性とスループットが得られます。
ノート:データベースのインスタンス障害が原因でトランザクションが終了した場合は、トランザクション全体がリカバリされる前に、ブロックレベルのリカバリによって行が使用可能になります。
ある行のロックを取得したトランザクションは、その行を含む表のロックも取得します。表ロックによって、現行のトランザクション内のデータ変更をオーバーライドするDDL操作の競合が防止されます。図12-2に、表の行3を更新する例を示します。Oracle AI Databaseでは、更新される行に排他ロックが、表には副排他ロックが自動的に設定されます。
図2: 行ロックと表ロック

-
行ロックと同時実行性このシナリオは、Oracle AI Databaseで同時実行性のために行ロックが使用されるかを示しています。
-
行ロックの記憶域ロック・マネージャを使用してロックのリストをメモリー内に保持する一部のデータベースとは異なり、Oracle AI Databaseでは、ロックした行を含むデータ・ブロックにロック情報が格納されます。
行ロックと同時実行性
このシナリオは、Oracle AI Databaseで同時実行性のために行ロックが使用されるかを示しています。
3つのセッションで同時に同じ行を問い合せます。セッション1およびセッション2では異なる行に対してコミットせずに更新しますが、セッション3では更新は行われません。各セッションでは、そのセッション自体で行った未コミットの更新を参照できますが、他のセッションによる未コミットの更新は参照できません。
表7データ同時実行性の例
| T | セッション 1 | セッション 2 | セッション 3 | 説明 |
|---|---|---|---|---|
| t0 | |
|
|
3つの異なるセッションから、従業員100および101のIDと給与が同時に問い合せます。それぞれの問合せからは、同じ結果が戻されます。 |
| t1 | |
セッション1で従業員100の給与を更新しますが、コミットはしません。更新時には、書込み側は更新する行に対してのみ行レベル・ロックを取得して、他の書込み側からこの行を変更されないようにします。 | ||
| t2 | |
|
|
各セッションが同時に元の問合せを発行します。セッション1では、t1での更新結果が反映された給与612が表示されます。セッション2およびセッション3における読取りでは、セッション1のトランザクション終了を待機せず、即座に行が戻されます。データベースでは、セッション1での更新前の状態の給与を表示するためにマルチバージョン読取り一貫性が使用されます。 |
| t3 | |
セッション2で従業員101の給与を更新しますが、トランザクションをコミットしません。更新時には、書込み側の行レベル・ロックは更新する行に対してのみ行レベル・ロックを取得することで、他の書込み側の行が変更されないようにします。 | ||
| t4 | |
|
|
各セッションが同時に元の問合せを発行します。セッション1では、t1で更新された給与612が表示されますが、セッション2で更新された従業員101の給与は表示されません。セッション2の読取り側では、セッション2によって更新された給与が表示されますが、セッション1で更新された給与は表示されません。セッション3での読取りでは、読取り一貫性を使用して、セッション1およびセッション2で変更される前の給与が表示されます。 |
関連情報:
-
V$LOCKについて学習するには、『Oracle AI Databaseリファレンス』をクリックします。
行ロックの記憶域
ロック・マネージャを使用してロックのリストをメモリー内に保持する一部のデータベースとは異なり、Oracle AI Databaseでは、ロックした行を含むデータ・ブロックにロック情報が格納されます。
Oracle Databaseでは、キューイング・メカニズムを使用して、行ロックを取得します。トランザクションで未ロックの行に対するロックが必要となった場合は、データ・ブロックにロックが配置されます。このトランザクションによって変更する各行は、ブロック・ヘッダーに格納されたトランザクションIDのコピーを指しています。
トランザクションが終了しても、トランザクションIDはそのままブロック・ヘッダーに残ります。別のトランザクションで行が変更される場合は、そのトランザクションIDを使用してロックがアクティブであるかどうかが判断されます。ロックがアクティブである場合は、ロックが解除されたときにセッションに通知されるように設定されます。ロックがアクティブでない場合は、そのトランザクションがロックを取得します。
関連情報:
-
データ・ブロック・ヘッダーについてさらに学習するには、「データ・ブロックの概要」を参照してください
-
V$TRANSACTIONについて学習するには、『Oracle AI Databaseリファレンス』を参照
表ロック(TM)
表ロック(TMロックとも呼ばれる)は、表がINSERT、UPDATE、DELETE、MERGE、FOR UPDATE句付きのSELECTまたはLOCK TABLE文によって変更される場合に、トランザクションによって取得されます。
DML操作では、トランザクションのために表へのDMLアクセスを確保して、このトランザクションと競合する可能性のあるDDL操作を防止するために表ロックが必要になります。
表ロックは、次のいずれかのモードで保持できます。
-
行共有(RS)
このロックは、サブ共有表ロック(SS)とも呼ばれ、表に対するロックを保持しているトランザクションがその表の行をロックしており、それらの行を更新する予定であることを示します。行共有ロックは、最も制限の緩やかなモードの表ロックであり、最高水準の同時実行性を表にもたらします。
-
行排他表ロック(RX)
このロックは、副排他表ロック(SX)とも呼ばれているため、一般的にロックを保持しているトランザクションが表の行を更新したか、
SELECT ... FOR UPDATEを発行したことを示します。SXロックでは、他のトランザクションが同じ表の行に対して問合せ、挿入、更新、削除またはロックを同時に実行できます。そのため、SXロックでは、複数のトランザクションが同じ表に対して同時にSXロックおよび副共有表ロックを取得できます。 -
共有表ロック(S)
トランザクションで共有表ロックを取得すると、他のトランザクションは表に対する
SELECT ... FOR UPDATEを使用しない問合せを実行できますが、更新は単一のトランザクションが共有表ロックを保持している場合にのみ許可されます。複数のトランザクションが共有表ロックを同時に保持することがあるため、トランザクションで表を変更できるかどうかは、このロックを保持しているのみでは保証されません。 -
共有行排他表ロック(SRX)
このロックは、共有副排他表ロック(SSX)とも呼ばれ、共有表ロックよりも多くの制限を課すものです。特定の表に対して、同時に1つのトランザクションのみがSSXロックを取得できます。トランザクションでSSXロックを取得すると、他のトランザクションは表に対して
SELECT ... FOR UPDATE以外の問合せを実行できますが、表は更新できません。 -
排他表ロック(X)
このロックは、最も制限が強くなります。他のトランザクションは、一切のDML文を実行できなくなり、表に一切のロックをかけられなくなります。
関連情報:
-
表ロックについてさらに学習するには、『Oracle AI Database開発ガイド』を参照してください。
ロックと外部キー
Oracle AI Databaseでは、親キーの同時実行性制御とそれに依存する外部キーの関連において、同時実行性制御は最適化されています。
ロックの動作は、外部キーの列が索引付けされているかどうかに依存します。外部キーが索引付けされていない場合、子表が頻繁にロックされ、デッドロックが発生し、同時実行性が低下する可能性があります。このため外部キーは、ほとんどの場合、索引付けが必要です。唯一の例外は、対応する一意キーまたは主キーの更新や削除が発生しないことが確実な場合です。
-
ロックと索引のない外部鍵子表の外部鍵列に索引が存在しない場合、データベースは子表の表に対する完全ロックを取得します。また、セッションによって、親表の主キーが変更されるか、親表の主キーが変更されるか、主キーの属性が変更された場合などで、親表の主キーが変更された場合、データベースは子表の表に対する完全ロックを取得します。
-
Locks and Indexed Foreign Keys The database does not acquire a full table lock on the child table when a foreign key column in the child table is indexed, and a session modifies a primary key in the parent table (for example, deletes a row or modifies primary key attributes) or merges rows into the parent table.
ロックと索引のない外部キー
子表の外部キー列に索引が存在せず、セッションによって(行の削除や主キーの属性の変更などで)親表の主キーが変更されるか、親表に行がマージされた場合、データベースは子表に対する完全表ロックを取得します。
次の両方の条件に当てはまる場合、データベースは子表に対する完全表ロックを取得します。
-
子表の外部キー列に索引が存在しない場合。
-
セッションで、親表の主キーが変更されるか(行の削除や主キーの属性の変更など)、親表に行がマージされた場合。ノート:親表に挿入すると、子表のDMLを妨げるブロック表ロックは取得されません。挿入の場合、データベースは子表に対するロックを取得します。これにより、構造変更は阻止されますが、既存の行または新規に追加された行の変更は阻止されません。
hr.departments表が、索引付けされていない外部キーemployees.department_idを含むhr.employeesの親である場合など。次の図に、departments表の部門60の主キー属性を変更するセッションを示します。
図3: 外部キーの索引がない場合のロック・メカニズム

図12-3では、データベースは、部門60の主キーの変更時にemployeesに対する完全表ロックを取得しています。このロックによって、他のセッションはemployees表の問合せはできますが、更新できなくなります。たとえば、セッションでは従業員の電話番号を更新できません。employeesに対する表ロックはdepartments表への主キーの変更が完了すると、即時に解除されます。departmentsの複数の行で主キーの変更が実行される場合、employeesに対する表ロックは、departmentsで変更される行ごとに取得および解除されます。ノート:子表に対するDMLは、親表に対する表ロックを取得しません。
ロックと索引付き外部キー
子表の外部キーの列が索引付けされていて、セッションによって、親表の主キーが変更された場合、データベースは子表の完全テーブルロックを取得しません。また、セッションによって、親表内の主キーが変更された場合(行の削除や、主キーの属性変更など)も、行を親表にマージする場合も、データベースではその子表の主キーがマージされます。
親表に対するロックにより、トランザクションは排他表ロックが、主キーの変更時に、親または子表に対するDMLは阻止されません。この状況は、子表への更新が発生している間に、親表での主キーの変更が発生する場合に適しています。図12-4に、department_id列が索引付けられた子表employeesを示します。トランザクションにより、部門280がdepartmentsから削除されます。この削除により、「ロックと索引のない外部キー」に示すようにデータベースがemployees表に対する完全テーブルロックを取得することはありません。
図4: 外部キーが索引付けされている場合のロック・メカニズム

子表でON DELETE CASCADEを指定すると、親表からの削除によって、子表からも削除することができます。たとえば、部門280を削除した場合、削除された部門の従業員に関するレコードをemployeesから削除できます。この場合、待機とロックに関するルールは、親表から行を削除した後に子表から行を削除する場合と同じです。
DDLロック
データ・ディクショナリ・ロック(DDLロック)によって、DDL操作によってオブジェクトに対する処理中または参照中に、そのオブジェクトの定義が保護されています。
DDL操作中には、修正や参照の対象となる個々のスキーマ・オブジェクトのみがロックされます。データ・ディクショナリ全体がロックされることはありません。
Oracle AI Databaseは、DDLロックを必要とするすべてのDDLトランザクションのために、DDLロックを自動的に取得します。ユーザーはDDLロックを明示的に要求できません。たとえば、ユーザーがストアド・プロシージャを作成する場合、Oracle AI Databaseはプロシージャ定義内で参照されるすべてのスキーマ・オブジェクトについてDDLロックを自動的に取得します。DDLロックにより、プロシージャ・コンパイルが完了する前にこれらのオブジェクトの変更または削除が防止されます。
-
排他DDLのロック排他DDLのロックにより、他のセッションでDDLのロックまたはDMLロックを取得できなくなります。
-
共有DDLロックリソースに対する共有DDLロックでは、競合するDDL操作の破壊的な干渉は防止されますが、同様のDDL操作でのデータ同時実行性は確保されています。
-
ブレーク可能解析ロックSQL文またはPL/SQLプログラム・ユニットは、参照する各スキーマ・オブジェクトについて解析ロックを保持します。
排他DDLロック
排他DDLロックは、他のセッションによるDDLロックまたはDMLロックの取得を防止します。
ほとんどのDDL操作では、同じスキーマ・オブジェクトを変更または参照する可能性のある他のDDL操作によって破壊的な干渉が起きないように、リソースの排他DDLロックが必要です。たとえば、ALTER TABLEで表に列を追加している間は、DROP TABLE操作でその表を削除できず、その逆も同様です。
排他DDLロックはDDL文実行の継続中と自動コミット中ずっと継続します。排他DDLロックの取得では、別の操作によってそのスキーマ・オブジェクトに対して別のDDLロックが保持されている場合、その取得は古いDDLロックが解除されるまで待機し、その後に処理されます。
関連項目: 「共有DDLロック」では、破壊的干渉を防止するううえで排他ロックが不要である状況について説明します
共有DDLロック
リソースに対する共有DDLロックでは、競合するDDL操作によって破壊的な干渉が防止されますが、同様のDDL操作でのデータ同時実行性は確保されます。
たとえば、CREATE PROCEDURE文の実行時には、その文を含むトランザクションは、参照されるすべての表について共有DDLロックを取得します。他のトランザクションでは、同じ表を参照するプロシージャを同時作成し、同じ表に対する共有DDLロックを同時取得できますが、参照される表に対して排他DDLロックを取得できるトランザクションはありません。
共有DDLロックはDDL文実行および自動コミットの間ずっと存続します。その結果、共有DDLロックを保持するトランザクションでは、参照中のスキーマ・オブジェクトの定義がそのトランザクションの継続時間にわたって変化しないことが保証されます。
ブレーク可能解析ロック
SQL文またはPL/SQLプログラム・ユニットは、参照する各スキーマ・オブジェクトについて解析ロックを保持します。
参照オブジェクトが変更または削除された場合に、対応する共有SQL領域を無効にできるようにするため、解析ロックは取得されます。解析ロックは、どのようなDDL操作 も拒否せず、矛盾するDDL操作も許可するためにブレーク(中断)できるため、ブレーク可能解析ロックと呼ばれます。
解析ロックは、SQL文実行の解析フェーズ中に共有プールで取得します。このロックは、その文の共有SQL領域がその共有プールに残っているかぎり保持されます。
関連項目: 「共有プール」
システム・ロック
Oracle AI Databaseでは、様々なタイプのシステム・ロックを使用して、内部データベースおよびメモリー構造を保護します。ユーザーは、システム・ロックの出現や継続期間を制御できないため、このメカニズムにはアクセスできません。
-
ラッチは、共有データ構造、オブジェクトおよびファイルへのマルチユーザー・アクセスを調整する、単純な低レベルのシリアライズ化メカニズムである。
-
相互排他オブジェクト(mutex)は、メモリー内のオブジェクトが複数の同時プロセスによってアクセスされた場合にエージ・アウトまたは破損しないようにするための低レベルのメカニズムである。mutexはラッチに似ていますが、通常、ラッチではオブジェクトのグループが保護されるのに対して、mutexでは単一のオブジェクトが保護されます。
-
内部ロック内部ロックは、ラッチやmutexよりも高レベルの複雑なメカニズムであり、様々な目的に使用されます。
ラッチ
ラッチは、共有データ構造、オブジェクトおよびファイルへのマルチユーザー・アクセスを調整する、単純な低レベルのシリアライズ化メカニズムである。
ラッチは、共有メモリー・リソースが複数プロセスによってアクセスされるときに破損しないように保護します。特に、ラッチは次の状況からデータ構造を保護します。
-
複数のセッションによる同時変更
-
あるセッションで変更中の場合の他のセッションによる読取り
-
アクセス中のメモリーの割当て解除(エージ・アウト)
通常、1つのラッチによってSGA内の複数のオブジェクトが保護されます。たとえば、DBWやLGWRなどのバックグラウンドプロセスでは、共有プールのメモリーを割り当てしてデータ構造を作成します。このメモリーを割り当てるために、これらのプロセスは、アクセスをシリアライズする共有プール・ラッチを使用して、2つのプロセスが共有プールを同時に検査または変更できないようにします。メモリーが割り当てられた後、解析に必要なライブラリ・キャッシュなどの共有プール領域に他のプロセスがアクセスする必要がある場合があります。この場合、共有プール全体ではなくライブラリ・キャッシュのみがラッチされます。
行ロックなどのエンキュー・ラッチとは異なり、ラッチではセッションのキューイングは許可されません。ラッチが使用可能になると、ラッチを要求する最初のセッションがラッチへの排他的アクセスを取得します。ラッチスピンの現象は、プロセスがループ内のラッチを繰り返しリクエストし、プロセスがラッチ要求を更新する前にCPUを解放するとラッチ・スリープが発生すると発生します。
通常、Oracleプロセスは、データ構造の1つを操作または参照する、非常に短い間のみラッチを取得します。たとえば、1人の従業員の給与更新の処理中に、データベースは数千のラッチを取得および解除する場合があります。ラッチの実装(特に、プロセスがラッチを待機するかどうか、およびどのくらいの時間待機するか)は、オペレーティング・システムに依存します。
ラッチの数を増やすと、同時実行可能な操作の数が減少します。たとえば、過剰なハード解析操作によって、ライブラリ・キャッシュ・ラッチの競合が生じます。V$LATCHビューには、各ラッチが要求された回数や待機された回数を含む、各ラッチの詳細な使用統計が含まれています。
関連情報:
-
V$LATCHについて学習するには、Oracle AI Databaseリファレンスを参照 -
待機イベント統計について学習するには、『Oracle AI Databaseパフォーマンス・チューニング・ガイド』を参照してください。
Mutex
相互排他オブジェクト(mutex)は、メモリー内のオブジェクトが同時プロセスによってアクセスされた場合にエージ・アウトまたは破損しないようにするための低レベルのメカニズムです。mutexはラッチに似ていますが、通常、ラッチではオブジェクトのグループが保護されるのに対して、mutexでは単一のオブジェクトが保護されます。
mutexには、複数の利点があります。
-
mutexによって、競合の可能性が減少します。
ラッチでは複数のオブジェクトを保護するため、複数のプロセスで保護対象のオブジェクトのいずれかへの同時アクセスが試行された場合に、ボトルネックが生じる可能性があります。mutexでは、グループではなく個別のオブジェクトへのアクセスをシリアライズするため、可用性が向上します。
-
mutexでは、ラッチよりも少ないメモリーが使用されます。
-
共有モードでmutexを使用すると、複数のセッションからの同時参照が可能になります。
内部ロック
内部ロックは、ラッチやmutexよりも高レベルで複雑なメカニズムであり、様々な目的に使用されます。
データベースでは、次のタイプの内部ロックを使用します。
-
ディクショナリ・キャッシュ・ロック
これらのロックの継続時間は非常に短く、ディクショナリ・キャッシュ内のエントリが修正されたり使用されている間、そのエントリについて保持されます。これらのロックは、解析されている文が矛盾したオブジェクト定義を参照しないことを保証します。ディクショナリ・キャッシュ・ロックは、共有または排他で保持されます。共有ロックは解析が完了すると解除されますが、排他ロックはDDL操作が完了したときに解除されます。
-
ファイルとログの管理ロック
これらのロックは様々なファイルを保護します。たとえば、ある内部ロックは制御ファイルを保護して、一度に1つのプロセスのみがそれを変更できるようにします。別のロックは、オンラインREDOログ・ファイルの使用とアーカイブを調整します。データベースを複数インスタンスが共有モードでマウントしたり、1つのインスタンスが排他モードでマウントすることを保証するために、データファイルがロックされます。ファイルとログのロックはファイルの状態を示すため、必然的に長い間保持されます。
-
表領域とUNDOセグメントのロック
これらのロックにより、表領域およびUNDOセグメントが保護されます。たとえば、データベースにアクセスするすべてのインスタンスは、表領域のオンライン/オフラインの状態について一致している必要があります。UNDOセグメントは、1つのセグメントに1つのデータベース・インスタンスしか書き込めないようにロックされています。
関連項目: 「データ辞書キャッシュ」
手動データ・ロックの概要
Oracle AI Databaseのデフォルトのロック・メカニズムは、手動でオーバーライドできます。
データの同時実行性、データの整合性および文レベルの読取り一貫性が確保するために、Oracle AI Databaseは自動的にロックを実行します。ただし、デフォルト・ロックの置換えは、次のような状況で有効です。
-
アプリケーションで、トランザクション・レベルの読取り一貫性またはリピータブル・リードが必要な場合。
この場合、問合せによって作成されるデータが、他のトランザクションによる変更を反映せず、トランザクションの継続時間にわたって一貫性を維持する必要があります。トランザクション・レベルの読取り一貫性は、明示的ロック、読取り専用トランザクション、シリアライズ可能トランザクションを使用するか、デフォルトのロックをオーバーライドすることで実現できます。
-
アプリケーションで、あるトランザクションが他のトランザクションの完了まで待機せずに済むように、そのトランザクションがリソースに排他的アクセスできるようにする必要がある場合。
Oracle AI Databaseの自動ロックは、セッション・レベルまたはトランザクション・レベルでオーバーライドできます。セッション・レベルでは、ALTER SESSION文を使用して必要なトランザクション分離レベルを設定できます。トランザクション・レベルでは、次のSQL文を含むトランザクションがOracle AI Databaseのデフォルト・ロックをオーバーライドします。
-
SET TRANSACTION ISOLATION LEVEL文 -
LOCK TABLE文(表をロックする文、またはビューを使用するときに実表をロックする文) -
SELECT ... FOR UPDATE文
前述の文で取得したロックは、トランザクション終了後に解除されるか、セーブポイントへのロールバックによって解除されます。
Oracle AI Databaseのデフォルト・ロックを任意のレベルで上書きする場合、データベース管理者やアプリケーション開発者は、ロックのオーバーライドの手順が確実に正しく実行されるようにしてください。ロックの手順は、データ整合性が保証される、データ同時実行性が許容範囲内である、デッドロックは発生する可能性がないかまたは適切に処理される、などの基準を満たすものにする必要があります。
関連情報:
-
LOCK TABLEおよびSELECTの説明は、『Oracle AI Database SQL言語リファレンス』を参照してください -
手動で表をロックする方法を学習するには、『Oracle AI Database開発ガイド』を参照
ユーザー定義ロックの概要
Oracle AI Databaseのロックマネージメント・サービスを使用すると、特定のアプリケーションで独自のロックを定義できます。
たとえば、ファイル・システム上のメッセージ・ログに対するアクセスをシリアライズするためのロックを作成できます。確保されたユーザー・ロックは、Oracle AI Databaseロックと同一であるため、デッドロックの検出などのOracle AI Databaseロックの機能をすべて備えています。ユーザー・ロックの接頭辞はULで識別されるため、Oracle AI Databaseロックと矛盾することはありません。
Oracle AI Databaseのロック管理サービスは、DBMS_LOCKパッケージ内のプロシージャを介して利用できます。PL/SQLブロックには、次の処理を行う文を含めることができます。
-
特定のタイプのロックを要求します。
-
そのロックに、同一のインスタンスまたは別のインスタンス内にある別のプロシージャからも識別できる、一意の名前を指定します。
-
ロック・タイプを変更します。
-
ロックを解放します
関連情報:
-
Oracle AI Database Lock Managementサービスの詳細は、『Oracle AI Database開発ガイド』を参照してください
-
DBMS_LOCKの詳細は、『Oracle AI Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。
脚注の説明
脚注1:
分散トランザクションの2フェーズ・コミットを処理する場合、特殊な状況では、データベースで読取りアクセスが一時的に禁止されることがあります。具体的には、問合せが準備フェーズとコミット・フェーズの間に開始され、コミット前にデータの読取りを試みる場合、データベースでは、読取りの整合性を保証するため、行レベルからブロック・レベルにロックが拡大されます。