主キーとして user_id を持つマップされた User オブジェクトと、一意の制約を持つメール列があるとします。ユーザー オブジェクトが存在しない場合にのみ、ユーザー オブジェクトをユーザー テーブルに保存するプログラムが必要です。
挿入関数で次のことができます。
- 取引開始
- 指定されたメールを持つユーザーのクエリ
- 存在しない場合は、新しいユーザーを作成し、セッションを使用して保存します
- 失敗した場合はコミットまたはロールバック
2 つの問題があります。
- 2 つのクエリを実行するのはコストがかかります。プレーン SQL を使用していた場合は、「INSERT IGNORE」構文を使用する可能性がありますが、私の場合は休止状態の保存メソッドを使用し、最後に User オブジェクトを保持したいと考えています。それに対する解決策はありますか?
- 同時実行。アプリケーションの 2 つのインスタンスが同時に実行される可能性はありますか? どちらも同じ「mail」パラメータで「addUser」関数を使用します。1 つ目はフェーズ 2 を通過し、そのメールを持つユーザーを見つけられません。最初のインスタンスがまだユーザーを保存してコミットしていないため、2 番目のインスタンスもユーザーを見つけることなくフェーズ 2 を通過します。次に、最初のインスタンスがユーザーを保存してコミットし、その後、2 番目のインスタンスがユーザーを保存してコミットします。このユーザーには、最初のインスタンスのメールと同じメールが含まれます。もちろん、制約のために失敗します。何か不足していますか?
私が正しい場合、どうすればよいですか:
- それが起こらないことを願っています。
- トランザクションの開始時に、ユーザー テーブルを読み取りおよび書き込み用にロックします。
- 関数に try...except を追加すると、一意の制約例外が除外されます。例外がスローされた場合は、メールに従ってデータベースからユーザーを選択するだけです。
- 他の解決策...