トランザクション処理とACIDサポート
このドキュメントでは、TigerGraphプラットフォームが提供するトランザクションサポートについて説明します。TigerGraphのトランザクションは、単一の論理的な作業単位として動作する一連の処理です。TigerGraphの読み取り専用処理は、頂点/エッジ属性値の変更、新しい頂点/エッジの挿入、既存の頂点/エッジの削除を行いません。TigerGraphの更新処理では、頂点/エッジ属性値の変更、新しい頂点/エッジの挿入、既存の頂点/エッジの削除を行います。
TigerGraphシステムは、逐次一貫性を備えた完全なACIDトランザクションを提供しています。トランザクションの定義は次の通りです。
-
各GSQLクエリはひとつのトランザクションです。各クエリには、複数の読み取りまたは書き込み処理が含まれる場合があります。
-
各REST++のGET、POST、DELETE処理(ここには複数の更新処理が含まれる場合があります)はひとつのトランザクションです。
不可分性
更新処理を伴うトランザクションでは、複数の頂点/エッジを挿入/削除したり、複数のエッジ/頂点の属性値を更新したりする場合があります。このような更新要求は「ゼロか100か」です。つまり、すべての変更が成功するか、ひとつも成功しないかのどちらかになります。
一貫性
TigerGraphシステムは、従来のACIDの考え方に則った整合性を提供します。トランザクションはデータ検証ルールを持つことができます。トランザクションはデータ検証ルールに則ってシステムを1つの有効な状態から別の有効な状態に移行します。
TigerGraphシステムは、分散システムの逐次一貫性も提供します。データのレプリカはすべて、同じ処理を同じ順序で実行します。これは、利用可能な最も強力な一貫性の形式の1つであり、たとえば因果一貫性などよりも強力です。
分離レベル
TigerGraphは、最も強力な分離形式である直列化可能分離レベルをサポートしています。内部的には、TigerGraphはMVCCを使用して分離を行っています。MVCC、つまりMulti-Version Concurrency Control(多版型同時実行制御)は、データベースの状態の複数のスナップショットを利用し、分離された同時操作をサポートします。原則的には、読み取りまたは書き込み処理1つごとに1つのスナップショットが存在します。
ダーティリード防止
読み取り専用トランザクションR1は、他の更新トランザクションが行ったコミットされていない変更を読み込みません。R1がシステムに送信される前または後にその更新トランザクションが送信されたかどうかには関わりません。
再現リード
単一のトランザクションT1の実行中に、T1が読み込んだ頂点またはエッジの属性値を変更する他の更新トランザクションがあった場合に、T1で同じデータを複数回読み取りしても、同じ結果を得ることができます。
ファントムリード防止
単一の読み取り専用トランザクションT1の実行中にT1が読み込んだ頂点またはエッジを削除/挿入した他の更新トランザクションがあった場合に、T1で同じデータを複数回読み取りしても、同じ結果を得ることができます。
永続性
コミットされたトランザクションはディスク(SSDまたはHDD)に書き込まれます。TigerGraphプラットフォームは、永続性を提供するためにログ先行書き込み(WAL)を備えています。
TigerGraph内部スナップショット機能
TigerGraphプラットフォームは、スナップショット/ MVCC(多版型同時実行制御)を使用して、並行操作の分離を行います。高レベルで、プラットフォームはグラフデータの複数のバージョン、スナップショットを一時的に維持することができます。トランザクションT1がシステムに送信されると、T1はグラフの最後の一貫したスナップショットで作業します。このスナップショットには、T1が送信される前にコミットされたトランザクションによって行われたすべての変更が反映されていますが、T1が送信されたときにまだコミットされていないトランザクションによって行われた変更は反映されていません。T1が作業しているグラフのバージョンは、T1以外のトランザクションによって(たとえT1が終了する前にコミットされた場合でも)変更されることはありません。
シナリオ例
トランザクション処理のシナリオをいくつか見てみましょう。
シナリオ1 読み込み - 書き込み
読み取り専用トランザクションR1が実行されています。R1が終了する前に、更新トランザクションW2が送信されてきました。R1が終了する前にW2が終了する可能性があります。しかしR1は、W2がコミットされる前にW2が行った変更を読み込みません(ダーティリードは起こりません)。R1が終了する前にW2がコミットされたとしても、R1が同じデータを複数回読み込んでも、W2が行った変更は読み込まれません(再現リード)。ファントムリードも発生しません。これは、R1が作業しているグラフバージョンは、前述のW2トランザクションのいずれによっても変更されないためです。つまり、R1がまだコミットされていないときにW2が開始すると、R1はW2が存在しなかったかのような結果を出します。
シナリオ2 書き込み - 読み込み
更新トランザクションW1が実行されています。W1がコミットされる前に、読み取り専用トランザクションR2が送信されてきました。R2はW1が終了するのを待たず、W1が存在しないかのように実行されます。その後、R2が終了する前にW1が終了してコミットした場合でも、R2はW1が行った変更を認識しません。これは、R2が作業を行うグラフバージョンがR2の送信時に固定されており、W1が行った変更が含まれないためです。つまり、W1がまだコミットされていないときにR2が開始すると、R2はW1が存在しなかったかのような結果を出します。
シナリオ3 書き込み - 書き込み
更新トランザクションW1が実行されています。W1が終了する前に、新しい更新リクエストW2が送信されてきました。W2は、W1が終了してから実行されます。複数の更新トランザクションが送信されると、システムは受信した時間が早い順にそれらを実行します。