4.2 注釈(NO)CHECKによるETAG計算のフィールドの包含/除外
更新操作の実行時にドキュメントの状態/バージョンのチェックに使用するドキュメントの部分を宣言的に指定するには、このようなドキュメントをサポートする二面性ビューの定義に注釈を付けます。
アプリケーションがドキュメントを更新するときに、更新するドキュメントのバージョン/状態が、ドキュメントが最後にデータベースから取得されてから変更されていないことを確認する必要があります。
これを実装する方法の1つは、ロックフリーであるオプティミスティックな同時実行性制御を使用することです。デフォルトでは、二面性ビューでサポートされるドキュメントはすべて、ETAGフィールドetag
の形式でドキュメント状態の署名を記録します。フィールド値は、ドキュメント・コンテンツやその他の情報のハッシュ値として構築され、ドキュメントが取得されるたびに自動的に更新されます。
ローカルで更新したドキュメントがアプリケーションによって書き込まれると、データベースは格納されたドキュメントの現在の状態について最新のETAG値を自動的に計算し、更新対象の(アプリケーションによって送信された)ドキュメントに埋め込まれたetag
値に対してこの値をチェックします。
2つの値が一致しない場合、更新操作は失敗します。その場合、アプリケーションは、データベースから最新バージョンのドキュメントを取得し、(フィールドetag
の新しい値を変更せずに)更新の必要に応じて変更し、(新たに変更された)ドキュメントの書込みを再試行できます。「二面性ビューでのオプティミスティックな同時実行性制御の使用」を参照してください。
デフォルトでは、ドキュメントのすべてのフィールドは、フィールドetag
の値の計算に関与します。特定のフィールドがこの計算に関与しないように除外するには、その列にキーワードNOCHECK
を付けます(更新可能性の注釈と同様に、WITH
の後に続けます)。
更新可能性の注釈と同様に、FROM
句にNOCHECK
を指定して、その句の影響を受けるすべての列に適用できます。その場合、CHECK
を使用して特定の列に注釈を付け、表レベルのNOCHECK
の影響から除外できます。
ただし、識別列には、表レベルの注釈に関係なく、必ず、ETAGの計算に関与するデフォルト動作があります。識別列をETAGの計算から除外するには、それに、列レベルの明示的な注釈であるNOCHECK
を指定する必要があります。
具体的に述べると、これは、ETAGチェックからドキュメント全体を除外するには特定している各列にNOCHECK
で明示的に注釈を付けるとともにすべての表(または他のすべての列)にNOCHECK
で注釈を付ける必要があるということです。
ノート:
NOCHECK
とNOUPDATE
の両方の注釈が付けられた列を更新しようとすると、エラーは発生せず、更新リクエストは単に無視されます。This is to prevent interfering with possible concurrency.
更新操作が成功すると、ETAG計算に関与しないフィールドの変更を含め、定義されている変更はすべて行われるため、その間に加えられた可能性があるそのフィールドの変更は上書きされます。つまり、ETAG計算に含まれないフィールドは、更新操作で無視されません。
たとえば、ビューdriver_dv
のフィールドteam
はドライバのチーム情報を含むオブジェクトであり、このチーム・オブジェクトのフィールドname
には例3-3でNOCHECK
という注釈が付けられています。つまり、チーム名はドライバ・ドキュメントのETAG値の計算に関与しません。
チーム名はドライバドキュメントのETAG計算に関与しないため、そのドキュメント内のチーム情報に対する変更は考慮されません。表teamはビューdriver_dv
の定義でNOUPDATE
とマークされているため、ドライバ・ドキュメントの更新時にそのチーム情報が無視されても問題はありません。
しかしながら、表team
が、そうではなくUPDATE
とマークされていたらどうでしょうか。その場合は、ドライバ・ドキュメントを更新すると、ドライバのチーム情報が更新される可能性があります。これは、表team
内のデータが変更されるということです。
アプリケーションでそのドライバのドキュメントが最後に読み取られてから、ドライバのチーム情報が外部でなんらかの形で変更されたとします。たとえば、チームの名前が"OLD Team Name"
から"NEW Team Name"
に変更された場合です。
その後、そのドライバ・ドキュメントを更新しても、チーム名の競合により失敗することはありません (別の理由で失敗する可能性はあります)。"NEW Team Name"
に対する以前の変更は、無視されるだけです。そのチーム名は、ドライバドキュメント更新操作で指定されたname
値("OLD Team Name"
など)で上書きされます。
更新操作で指定したドキュメントまたはドキュメント・フラグメントからチームのname
を省くだけで、この問題を回避できます(この問題は表team
をドライバ・ドキュメントを介して更新できる場合のみ発生する可能性があります)。
同様に、チーム・ドキュメントのフィールドdriver
はドライバ・オブジェクトの配列であり、それらのオブジェクトのフィールドpoints
にはNOCHECK
という注釈が付けられます(例3-1を参照)。したがって、(アプリケーションの)別のセッションによるそのフィールドへの変更はチーム・ドキュメントの更新を妨げません。(更新操作で無視されない、ETAG計算に含まれないフィールドについての注意事項は、ここでも当てはまります。)
全体としての二面性ビューでは、実際、列にNOCHECK
の注釈が付けられていない場合、そのドキュメントはETAGがチェックされています。すべての列がNOCHECK
の場合、ドキュメント・フィールドはETAGの計算に関与しません。これにより、パフォーマンスが向上し、大規模ドキュメントではさらに向上します。二面性ビューをすべてのETAGチェックから除外する場合のユースケースには、次のものがあります。
-
アプリケーションでは独自の方法で同時実行性を制御できるため、データベースのETAGチェックは必要ありません。
-
アプリケーションは単一スレッドであるため、同時に変更することはできません。
PL/SQLファンクションDBMS_JSON_SCHEMA.describe
を使用して、二面性ビューにETAGチェック済のドキュメントがあるかどうかを確認できます。その場合、上位レベルの配列フィールドproperties
には要素"check"
が含まれています。