1

Java/JDBC と MySQL を使用してアクティブ レコード パターンを実装し、並行処理のための楽観的ロックを実装しようとしています。

これで、テーブル内のすべてのレコードに「version_number」フィールドがあり、更新のたびにインクリメントされます。

これを実装するには2つの戦略があるようです:

  1. アプリケーションは、データを要求すると、各オブジェクト (レコードなど) の対応するバージョン番号も格納します。更新時に、バージョン番号がデータ層に「送信」され、UPDATE...SET...WHERE クエリで楽観的ロックに使用されます。
  2. アプリケーションはバージョン番号を保存しませんが、(データ行全体ではなく) オブジェクトの一部のみを保存します。楽観的ロックを成功させるには、データ層 (アクティブなレコード) が最初に DB から「行」をフェッチし、バージョン番号を取得してから、同じ UPDATE...SET...WHERE クエリを起動してレコードを更新する必要があります。

前者では、「最初のフェッチ」とその後の更新があります。後者の場合、「最初のフェッチ」だけでなく、更新の直前にフェッチがあります。

問題はこれです:設計上、どちらがより良いアプローチですか? バージョン番号を含むすべてのデータを Web アプリケーションのフロントエンド (Javascript/HTML) に保存することは大丈夫ですか? 安全ですか? それとも、更新前に読み取りのパフォーマンス ヒットを取得するほうがよいでしょうか?

この設計を実装する「正しい方法」はありますか? アクティブ レコードの現在の実装 (Ruby、Play、ActiveJDBC など) がこれをどのように処理しているかはわかりません。JDBC で「そのまま」実装する場合、この場合の正しい設計上の決定は何ですか?

4

2 に答える 2

1

ActiveJDBCはバージョン 1 を実装します。バージョン 2 では、競合状態が発生する可能性があります

于 2012-04-23T19:22:31.400 に答える
1

これはパフォーマンスの問題でもセキュリティの問題でもありません。2 つのアプローチは機能的に異なり、異なる目標を達成します。

最初のアプローチでは、ユーザーの「思考時間」全体にわたって行を楽観的にロックしています。ユーザー 1 が画面を読み込んでからユーザー 2 が変更を加えると、ユーザー 1 の変更は失敗し、古いデータを参照していたというエラーが表示されます。

2 番目のアプローチでは、競合するリクエスト スレッド間の書き込みのインターリーブから保護するだけです。ユーザー 1 がページを読み込んでから、ユーザー 2 が変更を加え、ユーザー 1 が送信を押すと、変更が反映され、ユーザー 2 の変更が吹き飛ばされます。ユーザー 1 は、古い情報に基づいて決定を下した可能性があり、それを知ることはありません。

どちらが技術的に「正しい」かではなく、ビジネス ルールにどの動作が必要かが問題です。どちらも有効ですが、異なることを行います。

于 2012-03-17T06:29:23.657 に答える