5

かなり複雑な Web アプリケーションで複数の MySQL InnoDB テーブルにまたがるデータを管理するためにトランザクションを使用しています。簡単に言えば、特定のトランザクションは次のように機能します。

  1. 「user_point_totals」テーブルの行からデータが読み取られます
  2. さまざまな策略が、ユーザーの新しいポイントの合計がどうあるべきかを計算します
  3. 更新された合計を反映して、「user_point_totals」テーブルに新しいエントリが作成されます

ユーザー A が、ポイントに関連する分岐を含む何らかのアクションを実行し、ステップ 1 が実行され、その実行スレッドがユーザーのポイント合計をメモリに読み取り、アプリケーションが新しい合計の計算を開始するとします。一方、ユーザー B は、ユーザー A のポイント合計に影響を与えるアクションを実行し、別のトランザクションが開始されます。ただし、最初のトランザクションはまだ完了していないため、2 番目のスレッドは最初のトランザクションと同じポイント合計値を (同じテーブル行から) 開始点として取得します。続いて、トランザクション 1 が完了し、新しい値がどうあるべきかを認識して新しいユーザー ポイントの合計を作成します。その後すぐに、トランザクション 2 が完了し、ユーザーのポイントの合計の新しい行も作成します。ただし、2 番目のトランザクションのポイント合計が正しくなくなり、

私の質問は次のとおりです。

  • トランザクションのアトミックな性質のために、このシナリオは不可能ですか?
  • そうでない場合、この種の状況でデータの整合性が存在することをどのように保証しますか?

ご検討いただきありがとうございます。

4

1 に答える 1

3

技術レベルでは、MySQL のテーブル ロック(または行ロック) 機能を使用できます。これにより、誰かが実際にテーブルを使用して何かを計算しているかどうかを検出できます。一方、この手法では、プロセスがクラッシュした場合に何が起こるかなど、多くの考慮事項が必要になります。

ただし、実際のレベルでは、このようなことをしたいとは思いません。MySQL の sum() や avg() などの演算子は、このニーズに合わせて既に最適化されています。テーブルのいくつかの列を合計してテーブルで答えを得る必要がある場合は、ビューを使用するか、一時テーブルを作成できます (可能ですが遅くなります)。他の列から計算できる値を含む列を持つべきではありません。この状況は、関係のバランスがとれていない場合、どのフィールドが真であるかが不明確であるため、不適合につながります。(これは入力スクリプト エラーですか、それともプログラマーによる意図的なフィールドの再利用ですか?)

2 つ目の注意として、MySQL インスタンスでは必ず InnoDB テーブルを使用してください。そうしないと、システムが完全に ACID に準拠していないため、必要なアトミック性が得られません。

于 2010-09-22T14:15:31.540 に答える