2

Google App Engineのドキュメントを読んでいて、よくわからないことがありました。

データストアは、楽観的同時実行性を使用してトランザクションを管理します。2つ以上のアプリケーションインスタンスが同じエンティティグループを同時に変更しようとすると(既存のエンティティを更新するか、新しいエンティティを作成することにより)、変更をコミットする最初のアプリケーションは成功し、他のすべてのアプリケーションはコミットに失敗します。これらの他のアプリケーションは、トランザクションを再試行して、更新されたデータに適用できます。データストアはこのように機能するため、エンティティグループを使用すると、特定のグループ内の任意のエンティティに対して実行できる同時書き込みの数が制限されることに注意してください。

これは、2つの異なるデバイスの2人の異なるユーザーが同じオブジェクトを変更しようとした場合、そのうちの1つだけが成功することを意味しますか?これは典型的なデータベースの動作ですか、それとも単なるGAEの制限ですか?2人以上のユーザーが同じオブジェクトを変更しようとするような状況を、他のデータベースは通常どのように処理しますか?

また、2つ以上のアプリケーションインスタンスが新しいエンティティを作成しようとすると、1つだけが成功するという事実はどういう意味ですか。私はそれが間違っていることを理解していますか?2つのアプリケーションインスタンスが同じテーブルに新しいオブジェクトを追加することはできませんか?

4

2 に答える 2

5

MongoDBなどのドキュメントデータベース(別名NoSQL)について話すことはできませんが、リレーショナルデータベースでは1つの操作しか有効にできません。ただし、これは操作何であるかに帰着します。

たとえば、2人のユーザーが同じオブジェクトを変更しようとしたとします。それらの変更が列のサブセットのみを変更する場合、たとえば...

ユーザー1:

update MyTable set Col1 = '1', Col2 = '2' where ID = 'abc'

ユーザー2:

update MyTable set Col2 = 'x', Col3 = 'y' where ID = 'abc'

確実Col1に「1」になり、Col3' will be 'y', as those two columns were only updated in one statement. The value ofCol2`は最後に実行されたコマンドによって決定されます。

同様に、あるユーザーが行を更新し、別のユーザーが行を削除した場合、その行は何があっても削除されます。ユーザーの更新コマンドが最初に来た場合、更新は成功し、行は削除されます。削除コマンドが最初に来た場合、行は最初に削除され、行が存在しないため、更新は何もしません(where句はどの行とも一致しません)。

ただし、実際には、変更された列のみを含むコマンドを使用してデータベースに更新を発行することを気にするアプリケーションはほとんどありません。ほとんどすべてのアプリケーションでは、コマンドはテーブルレベルで作成され、すべての列を更新してから、「現在の」(変更されているかどうかに関係なく)値がこれらのコマンドに渡されます。これが、楽観的同時実行性を使用する理由です。

abcその行に現在値があると仮定します。

ID = 'abc'
Col1 = '1_original'
Col2 = '2_original'
Col3 = '3_original'

また、両方のユーザーが同時に行を取得した場合、上記のコマンドはより現実的に次のようになります。

ユーザー1:

update MyTable set Col1 = '1', Col2 = '2', Col3 = '3_original' where ID = 'abc'

ユーザー2:

update MyTable set Col1 = '1_original', Col2 = 'x', Col3 = 'y' where ID = 'abc'

今、問題があります。2番目のコマンドは実際にはの値を気にしませんがCol1、ユーザー1によって設定された値を上書きする可能性があります。同様に、ユーザー2が最初にヒットした場合、ユーザー1はCol3ユーザー2によって書き込まれた値を上書きします。

楽観的同時実行性は、基本的に句を拡張して、テーブルのキーだけでなく、すべてwhereの列の値をチェックします。このようにして、行を取得してから保存し直すまでの間に、他の誰か(または何か)によって行われた変更を上書きしないようにすることができます。

したがって、同じ条件が与えられると、コマンドは次のようになります。

ユーザー1:

update MyTable set Col1 = '1', Col2 = '2', Col3 = '3_original' where ID = 'abc' 
        and Col1 = '1_original' and Col2 = '2_original' and Col3 = '3_original'

ユーザー2:

update MyTable set Col1 = '1_original', Col2 = 'x', Col3 = 'y' where ID = 'abc'
        and Col1 = '1_original' and Col2 = '2_original' and Col3 = '3_original'

つまり、列が元の値を持たなくなるため、データベースに最後にヒットしたコマンドは実際には何も実行されません。

于 2012-04-14T03:34:08.387 に答える
5

トランザクションのAPIは数回再試行します(デフォルトは3回、合計4回の試行)。トランザクション関数がエンティティの読み取り、プロパティの更新、書き戻し、再試行も再読み取りなどを行うと仮定します。したがって、通常、激しい競合がない限り、失敗に気付くことはありません。

挿入について少し読み間違えました。通常、インサートは異なるキーを使用するため、競合はまったく発生しません。(アプリで明示的に同じキーを設定した場合にのみ、同じキーを使用します。)

于 2012-04-14T04:40:27.643 に答える