クラウドにデータを保持するデスクトップアプリケーションを作成しています。私が心配していることの1つは、アプリケーションでアイテムを編集し始めてしばらく放置すると、データが古くなることです。これは、2人が同じアイテムを同時に編集しようとした場合にも発生する可能性があります。編集が完了してデータを保存したい場合は、データベースに現在存在するものを上書きするか、最後の変更後に編集を開始したことを確認し、変更を強制的に破棄するか、リスクを与えるオプションを与える必要があります。他の誰かの変更を上書きする。
フィールドの追加について考えましたis_locked
およびlock_timestamp
をDBテーブルに追加します。ユーザーがアイテムの編集を開始すると、行が変更されますis_locked
をtrueに設定し、ロックタイムスタンプを現在の時刻に設定します。その後、ロックが保持される時間を確保します(例:5分)。他の誰かがアイテムを編集しようとすると、アイテムがロックされていて、ロックが自動的に期限切れになると、メッセージが表示されます。ロックの編集中にユーザーが離れると、ロックは比較的短期間で自動的に期限切れになり、ロックが期限切れになると警告が表示され、データの更新後に強制的に編集を再開する必要があります。
これは古いデータの上書きを防ぐための良い方法でしょうか?それはやりすぎですか(アプリケーションが1つのアカウントで数人以上のユーザーによって同時に使用されることはないと思います)。
(もう1つの懸念は、2人が同じアイテムのロックを取得することですが、それは私が快適なレース状態だと思います。)
ここで役立つ1つのことは用語です。ここで説明しているのは「悲観的ロック」と呼ばれるものです。このアプローチの主な代替手段は「楽観的ロック」です。悲観的ロックでは、各アクターはレコードを更新する前にロックし、更新が完了したらロックを解放する必要があります。楽観的ロックでは、他の誰もレコードを更新していないと想定して試行します。レコードが他のアクタによって変更された場合、更新は失敗します。
2つのアクターが同時に同じものを更新する可能性が低い場合は、一般的に楽観的ロックが推奨されます。悲観論は通常、その可能性が高い場合、または開始前に更新が成功することを知る必要がある場合に使用されます。私の経験では、悲観的ロックに固有の多くの問題があるため、ほとんどの場合、楽観的ロックが推奨されます。最大の問題の1つが質問で触れられています。ユーザーは編集のためにレコードをロックしてから、昼食に出ることができます。あなたの緩和策はそれを助けますが、ユーザーエクスペリエンスは楽観的なアプローチよりも良くなく、はるかに悪い可能性があります。たとえば、あるユーザーがレコードを開いて更新を開始すると、上司が自分のデスクに現れます。別のユーザーがレコードを編集しようとしました。それはロックされている。 2番目のユーザーは試行を続け、5分後にロックが期限切れになり、2番目のユーザーがレコードを更新します。最初のユーザーは画面に戻り、保存を試み、ロックを失ったと通知されます。楽観的ロックの使用を除いてすべてが同じである同じシナリオで、最初のユーザーのエクスペリエンスはほとんど同じですが、2番目のユーザーは5分間待機しません。
レイアウトするスキームは、ロック値にオプティミスティックロックを実装することで大幅に改善されますが、楽観的ロックはおそらく全体で問題なく、is_lockedフィールドを取り除くことができると思います。
使用している「クラウドDB」を提供していません。独自のソリューションを実装する前に、その機能を調べて、組み込みの機能があるかどうかを確認する必要があります。
基本的なレシピは次のとおりです。is_lockedフィールドの代わりに、バージョン番号フィールドがあります。レコードを取得するとき、レコードの現在のバージョンを取得します。更新するときは、取得した内容と一致するバージョンフィールドを条件として更新を行い、成功した場合は更新します。バージョンが一致しない場合、更新は効果がなく、失敗として報告します。
@ JimmyJamesの回答 から、ユーザーエクスペリエンスについての質問の実際がどのようであるかがわかります。
それはすべてコンテキストに依存します。レコードの更新にはどのくらいの時間と労力がかかりますか?複数のユーザーが同じドキュメントを更新する頻度はどれくらいですか?
たとえば、ユーザーがレコードを更新するのに通常数秒かかり、競合がほとんどない場合、楽観的ロックがおそらく最適な方法です。最悪の場合、ユーザーはドキュメントを更新するためにさらに数秒、場合によっては最大1分を費やす必要があります。
文書が非常に論争を起こしているが適切に構成されている場合は、30秒刻みで個々のフィールドをロックして、タイマーまたは目立たない通知を表示して、ロックを延長できるようにすることができます。
ただし、ユーザーがかなりの時間や労力を費やしている場合は、他のアプローチを検討する必要があります。レコードはうまく構成されていますか?サーバー上のバージョンとユーザーが保存しようとしているバージョンとの比較(差分)をユーザーに示すことができますか?違いを強調できますか?変更をマージマージできますか?ソース管理ツールで体験したいことを考えてください。あなたは本当にそのすべてのコードを再び書くことを強制されたくありません!
追加のインスピレーションを得るためにGoogleドキュメントを見ることができます。おそらく、新しいバージョンが保存されたことをユーザーに通知することができます。多分あなたは彼らがより論争の少ない時間に戻ってくることを選ぶことができるように何人の人々がレコードを開いているか彼らに示すことができます。