需求是这样的:
用户每天最多领取礼包3次,每次insert一条记录,但是在并发的情况下会超出3次,如果解决?
有个已知的方法如下,但是并发下会产生死锁
INSERT INTO t_test (gift_id, user_id, `date`) SELECT v_gift_id, v_user_id, v_date FROM dual WHERE not exists (select * from t_test where `user_id` = v_user_id and `date` = v_date GROUP BY `user_id`, `date` HAVING count(*) > 2);
@junze が言ったように、通常は
redis
で行われます。例えば、
の場合redis
にはユーザーごとの回数insert
を格納します。key
形式がuser:count
まず、毎回
これにより、3 を超える高い同時実行を回避できます。count
の値を確認し、3 未満の場合は挿入を実行し、insert
の結果を判定します。挿入が成功した場合は、key、user:count
を実行します。 >incr
となり、書き込みは失敗します。incr user:count
は実行されません。incr
の有効期限
key
を 1 日に設定でき、1 日後にキーは削除され、翌日に再初期化されます。expire user:count 60*60*24
カウントには Redis の文字列タイプを使用します。Redis は高い同時実行性をより適切にサポートします。
MySQL では、ユーザーのギフト パッケージの数をキャッシュに保存し、ユーザーの ID に基づいてキャッシュ キーとして定数を追加し、その数を保存し、毎回キャッシュから取得することはできません。挿入された回数を取り出し、自分の回数より少ないかどうかを判断し、少なくない場合は続行します。続行すると、挿入後に数値が 1 つ増加し、キャッシュに配置されます。
ロジック層で行うことをお勧めします
Mysqlにはこの仕組みは無いようで、この制御も論理制御な気がします
これを行うために mysql を使用する必要がある場合は、トランザクションを使用して確実に実行してください。