適用対象: NoSQL
データベース トランザクションでは、データの同時変更に対応する、安全で予測可能なプログラミング モデルが提供されます。 SQL Server などの従来のリレーショナル データベースを使用すると、ストアド プロシージャとトリガーを使用してビジネス ロジックを記述し、データベース エンジン内で直接実行するためにサーバーに送信できます。
従来のリレーショナル データベースでは、2 つの異なるプログラミング言語 (JavaScript、Python、C#、Java などの非トランザクション アプリケーション プログラミング言語) を扱う必要があります。および T-SQL などのトランザクション プログラミング言語は、データベースによってネイティブに実行されます。
Azure Cosmos DB のデータベース エンジンは、スナップショット分離を使用して、ACID (原子性、整合性、分離、持続性) に準拠した完全なトランザクションをサポートします。 コンテナーの 論理パーティション のスコープ内のすべてのデータベース操作は、パーティションのレプリカによってホストされているデータベース エンジン内でトランザクション的に実行されます。 これらの操作には、書き込み操作 (論理パーティション内の 1 つまたは複数の項目の更新) と読み取り操作の両方が含まれます。
次の表に、さまざまな操作とトランザクションの種類を示します。
操作 | 操作の種類 | 単一または複数項目のトランザクション |
---|---|---|
挿入 (事前/事後トリガーなし) | 書き込み | 単一項目のトランザクション |
挿入 (事前/事後トリガーを使用) | 書き込みと読み取り | 複数項目のトランザクション |
置換 (事前/事後トリガーなし) | 書き込み | 単一項目のトランザクション |
置換 (事前/事後トリガーを使用) | 読み書き | 複数項目のトランザクション |
Upsert (事前/事後トリガーなし) | 書き込み | 単一項目のトランザクション |
Upsert (事前/事後トリガーを使用) | 読み書き | 複数項目のトランザクション |
削除 (事前/事後トリガーなし) | 書き込み | 単一項目のトランザクション |
削除 (事前/事後トリガーを使用) | 書き込みと読み取り | 複数項目のトランザクション |
ストアド プロシージャの実行 | 読み書き | 複数項目のトランザクション |
システムによって開始されるマージ プロシージャの実行 | 書き込み | 複数項目のトランザクション |
項目の有効期限 (TTL) に基づいて、システムによって開始される項目削除の実行 | 書き込み | 複数項目のトランザクション |
お読みください | お読みください | 単一項目のトランザクション |
変更フィード | お読みください | 複数項目のトランザクション |
改ページ対応読み取り | お読みください | 複数項目のトランザクション |
ページ分割されたクエリ | お読みください | 複数項目のトランザクション |
ページ分割されたクエリの一部として UDF を実行 | お読みください | 複数項目のトランザクション |
複数項目のトランザクション
Azure Cosmos DB では 、JavaScript でストアド プロシージャ、トリガー、およびユーザー定義関数 とマージ プロシージャを記述できます。 Azure Cosmos DB のデータベース エンジン内では、JavaScript の実行がネイティブでサポートされています。 ストアド プロシージャ、プリ/ポスト トリガー、ユーザー定義関数 (UDF)、マージ プロシージャをコンテナーに登録し、後で Azure Cosmos DB データベース エンジン内でトランザクションで実行できます。 JavaScript でアプリケーション ロジックを記述する場合、制御フロー、変数のスコーピング、割り当て、およびデータベース トランザクション内での例外処理プリミティブの直接統合を JavaScript プログラミング言語で自然に表現することができます。
JavaScript ベースのストアド プロシージャ、トリガー、UDF、およびマージ プロシージャは、論理パーティション内のすべての項目でのスナップショット分離によって、アンビエント ACID トランザクション内にラップされます。 実行中に JavaScript プログラムが例外をスローすると、トランザクション全体が中止され、ロールバックされます。 結果のプログラミング モデルは簡潔でありながら強力なものになります。 JavaScript 開発者は、使い慣れた言語コンストラクトとライブラリ プリミティブを引き続き利用しながら、耐性のあるプログラミング モデルを手に入れることができます。
データベース エンジン内部で JavaScript を直接実行する機能により、コンテナーの項目に対するデータベース操作が高いパフォーマンスでトランザクション実行されます。 さらに、Azure Cosmos DB データベース エンジンは JSON と JavaScript をネイティブにサポートしているため、アプリケーションの型システムとデータベースの間にインピーダンスの不一致はありません。
オプティミスティック コンカレンシー
オプティミスティック コンカレンシー制御 (OCC) を使用すると、更新や削除が失われるのを防ぐことができます。 競合する同時実行操作は、項目を保持する論理パーティションによってホストされているデータベース エンジンの通常の排他的ロックの対象となります。 2 つの同時実行操作が論理パーティション内の項目の最新バージョンの更新を試みると、そのうちの 1 つが優先され、もう 1 つの操作が失敗します。 ただし、同じ項目を同時に更新しようとする 1 つまたは 2 つの操作が以前にアイテムの古い値を読み取っていた場合、競合する操作のいずれかまたは両方によって以前に読み取られた値が実際にアイテムの最新の値であったかどうかは、データベースでは認識されません。
さいわい、この状況は、2 つの操作がデータベース エンジン内のトランザクション境界に入る前に、OCC で検出できます。 OCC は、他のユーザーによって行われた変更を誤って上書きしないようにデータを保護します。 また、ご自分が加えた変更により他のユーザーのデータが誤って上書きされることも防ぎます。
ETag ヘッダーと HTTP ヘッダーを使用してオプティミスティック コンカレンシー制御を実装する
Azure Cosmos DB コンテナーに格納されている項目はすべて、システム定義の _etag
プロパティを備えています。 _etag
の値は、項目が更新されるたびに、サーバーによって自動的に作成および更新されます。 _etag
をクライアントによって指定される if-match
要求ヘッダーと共に使用して、サーバーで項目を条件付きで更新できるどうかを判別できます。 if-match
ヘッダーの値がサーバーの_etag
の値と一致する場合は、アイテムが更新されます。 if-match
要求ヘッダーの値が最新ではなくなると、操作はサーバーによって拒否され、"HTTP 412 前提条件エラー" という応答メッセージが返されます。 その後、クライアントはアイテムを再フェッチして、サーバー上のアイテムの現在のバージョンを取得するか、サーバー内のアイテムのバージョンをアイテムの独自の _etag
値でオーバーライドできます。 また、_etag
を if-none-match
ヘッダーと共に使用して、リソースの再フェッチが必要かどうかを判断できます。
項目の _etag
値は、項目が更新されるたびに変更されます。 項目の置換操作の場合、if-match
が要求オプションの一部として明示されている必要があります。 例については、 GitHub のサンプル コードを参照してください。 _etag
値は、ストアド プロシージャによって操作されるすべての書き込み項目に対して暗黙的にチェックされます。 競合が検出されると、ストアド プロシージャによってトランザクションがロールバックされ、例外がスローされます。 この方法では、ストアド プロシージャ内のすべての書き込みまたは書き込みなしがアトミックに適用されます。 これは、更新を再び適用し、元のクライアント要求を再試行することをアプリケーションに求めるシグナルです。
オプティミスティック同時実行制御とグローバル分散
項目の同時更新は、Azure Cosmos DB の通信プロトコル レイヤーによって OCC の管理下に置かれます。 単一リージョンの書き込み用に構成された Azure Cosmos DB アカウントの場合、Azure Cosmos DB は、更新 (または削除) するアイテムのクライアント側のバージョンが、Azure Cosmos DB コンテナー内の項目のバージョンと同じであることを確認します。 これにより、ご自分の書き込みが他のユーザーの書き込みによって誤って上書きされたり、その逆のケースが生じたりしないように、確実に保護されます。 マルチユーザー環境では、オプティミスティック コンカレンシー制御によって、誤ってアイテムのバージョンが誤って削除または更新されないように保護されます。 したがって、項目が "更新によるデータ喪失" または "削除によるデータ喪失" という悩ましい問題から保護されます。
複数リージョン書き込みで構成された Azure Cosmos DB アカウントでは、データの _etag
がローカル リージョン内のデータのものと一致する場合、データをセカンダリ リージョンに個別にコミットできます。 セカンダリ リージョンで新しいデータがローカルにコミットされると、ハブまたはプライマリ リージョンにマージされます。 競合解決ポリシーによって新しいデータがハブ リージョンにマージされた場合、このデータは新しい _etag
でグローバルにレプリケートされます。 競合解決ポリシーによって新しいデータが拒否された場合、セカンダリ リージョンは元のデータにロールバックされ、 _etag
。
次のステップ
データベース トランザクションとオプティミスティック コンカレンシー制御の詳細については、以下を参照してください。