33

私はデータベーステーブル(正規化、MS SQLサーバー上)を設計し、少数のユーザーが情報を追加および編集するために使用するアプリケーション用のスタンドアロンWindowsフロントエンドを作成しました。後日、生産エリア全体を検索できるようにWebインターフェイスを追加します。

2人のユーザーが同じレコードの編集を開始した場合、最後に更新をコミットすると「勝者」になり、重要な情報が失われる可能性があるのではないかと心配しています。いくつかの解決策が思い浮かびますが、私がより大きな頭痛を引き起こすかどうかはわかりません。

  1. 何もせず、2人のユーザーが同じレコードを同時に編集しないことを期待してください。-ハッピングされたことがないかもしれませんが、ハプされた場合はどうなりますか?
  2. 編集ルーチンは、元のデータと更新のコピーを保存し、ユーザーが編集を終了したときに比較することができます。それらが異なる場合は、showuserとcomfirmupdate-データの2つのコピーを保存する必要があります。
  3. 最後に更新されたDATETIME列を追加し、更新時に一致するかどうかを確認します。一致しない場合は、違いを表示します。-関連する各テーブルに新しい列が必要です。
  4. ユーザーがチェックされるレコードの編集を開始したときに登録する編集テーブルを作成し、他のユーザーが同じレコードを編集できないようにします。-ユーザーがプログラムからクラッシュした場合にデッドロックやレコードがロックされるのを防ぐために、プログラムフローを慎重に検討する必要があります。

より良い解決策はありますか、それとも私はこれらのいずれかに行くべきですか?

4

8 に答える 8

16

衝突の頻度が低いと予想される場合は、楽観的同時実行制御がおそらく最善の策です。

Scott Mitchellは、そのパターンの実装に関する包括的なチュートリアルを作成しました。
楽観的並行性の実装

于 2008-08-03T21:31:40.187 に答える
4

古典的なアプローチは次のとおりです。

  • 各テーブルに「ロックされた」ブールフィールドを追加します。
  • これをデフォルトで false に設定します。
  • ユーザーが編集を開始したら、次のようにします。

    • 行をロックします (行をロックできない場合はテーブル全体をロックします)。
    • 編集したい行のフラグをチェックしてください
    • フラグが true の場合
      • 現時点ではその行を編集できないことをユーザーに通知します
    • そうしないと
      • フラグをtrueに設定します
    • ロックを解除する

    • レコードを保存するときに、フラグを false に戻します

于 2008-10-01T08:53:19.470 に答える
2

@ Mark Harrison : SQL Server はその構文 ( ) をサポートしていませんSELECT ... FOR UPDATE

SQL Server に相当するのはSELECTステートメント ヒントUPDLOCKです。

詳細については、 SQL Server Books Onlineを参照してください。

于 2008-08-04T21:54:15.463 に答える
2

- 最初にフィールド (更新時刻) を作成して最後の更新レコードを保存します - ユーザーがレコードを選択して選択時刻を保存すると、選択時刻と更新時刻フィールドを比較します (更新時刻) > (選択時刻) の場合は、別のユーザーが選択後にこのレコードを更新することを意味します記録

于 2016-07-14T11:23:05.980 に答える
1

もう 1 つのオプションは、変更しているレコードの値が変更を開始したときと同じであることをテストすることです。

SELECT 
    customer_nm,
    customer_nm AS customer_nm_orig
FROM demo_customer
WHERE customer_id = @p_customer_id

(customer_nm フィールドを表示し、ユーザーが変更します)

UPDATE demo_customer
SET customer_nm = @p_customer_name_new
WHERE customer_id = @p_customer_id
AND customer_name = @p_customer_nm_old

IF @@ROWCOUNT = 0
    RAISERROR( 'Update failed: Data changed' );

テーブルに新しい列を追加する (そして最新の状態に保つ) 必要はありませんが、より詳細な SQL ステートメントを作成し、新しいフィールドと古いフィールドをストアド プロシージャに渡す必要があります。

また、レコードをロックしていないという利点もあります。

于 2008-08-13T22:32:37.230 に答える
1

SELECT FOR UPDATE と同等の機能は、微視的な時間だけロックを保持する場合に適していますが、巨視的な時間 (たとえば、ユーザーがデータをロードし、「保存」を押していない場合など) は、上記のように楽観的同時実行を使用する必要があります。私はいつも間違った名前だと思っています - それは「最後のライターが勝つ」よりも悲観的です.

于 2008-10-01T05:39:22.883 に答える
0

私の場合、列lastupdate(timetampデータ型)を取得する最良の方法です。選択して更新するときは、この値を比較するだけです。このソリューションのもう1つの利点は、この列を使用して、データが変更された時間を追跡できることです。チェック更新のためにisLockのような列を作成するだけでは良くないと思います。

于 2011-06-24T07:14:00.870 に答える
0

データベースがこれを行います。このようなことのためだけに設計された「select...forupdate」を見てください。選択した行に書き込みロックが適用され、コミットまたはロールバックできます。

于 2008-08-04T02:30:09.227 に答える