2

私のモデル:

class Order(models.Model):
    property_a = models.CharField()
    property_b = models.CharField()
    property_c = models.CharField()

多くのユーザーが管理者変更ページを介して短時間で特定のレコードにアクセスするため、同時実行の問題が発生しています。

ユーザー 1 と 2 が同時に変更ページを開きます。ページをロードするときにすべての値が空白であると想定します。ユーザー 1 は、property_a を「a」に、property_b を「b」に設定して保存します。1 秒後にユーザー 2 がプロパティ b を変更して c を保存すると、ユーザー 1 のすべての値が静かに上書きされます。この場合、property_a は空白に戻り、b と c はユーザー 2 が入力したものになります。

これを処理する方法についての推奨事項が必要です。モデルにバージョン フィールドが必要な場合、それを管理者に渡すにはどうすればよいですか? 別のユーザーがレコードを変更したために変更を保存できないことをユーザーにエレガントに通知できるようにするには、どこでチェックを行えばよいでしょうか? ユーザーにエラーを返すよりシームレスな方法はありますか?

4

1 に答える 1

0

標準的な解決策は、ユーザーが 1 つのレコードを共有できないようにすることです。Order非常に多くのユーザーがまったく同じインスタンスをいじっている理由はまったく明らかではありません。

Orderおそらく複合オブジェクトであり、単一のモデルに多くを入れすぎていると考えてください。それが最初の、そして最良の解決策です。

(不可解な理由で) これを分解しない場合は、2 部構成の更新トランザクションを作成する必要があります。

  1. データを再クエリします。このユーザーのセッションで行われた元のクエリと比較します。

  2. データが元のクエリと一致しない場合は、他の誰かが変更したことになります。ユーザーの変更は無効化、ロールバック、消去され、ユーザーには新しいクエリが表示されます。

  3. データが一致する場合は、変更のコミットを試みることができます。

上記のアルゴリズムには競合状態があり、通常は低レベルの SQL によって解決されます。ユーザーの作業が無効になり、非常にイライラすることに注意してください。

そのため、最初の選択肢は、モデルを分解して同時実行性を排除することです。


私のモデルにはその他のメモ フィールドがあります

これは悪い設計です。(a) このフィールドでの衝突によって並行性が失われます。(b) コメントのログや履歴はありません。

項目 (b) は、行儀の悪いユーザーが悪意を持ってこのデータを破壊できることを意味します。メモやコメントをログとして保存すると、原則として、ユーザーが自分のコメントのみを変更できるように制限できます。

[「その他のメモ」を含むほとんどのデータベースでは、フィールドは、重要だが解析不可能なデータでいっぱいの、費用がかかり、維持するのが難しい問題になっています。その他のメモは、ユーザーがアプリケーション ソフトウェアの外部で独自のプロセスを発明する場所です。]

「その他のメモ」はログのように扱われ、無制限の数のメモ -- 日付スタンプ付き -- ユーザーによって識別されます --が注文に追加されます。

設計を単純に分割してメモを別のテーブルに配置すると、同時実行性の問題が解決されます。

于 2010-06-25T01:38:50.140 に答える