2012-11-06 6 views
6

私は自分のサイトのユーザーに自分のポイントに基づいてランク付けをするポイントシステムに取り組んでいます。プロフィールページをチェックするたびにユーザーに+1ポイントを与えています。ユーザーが200ポイントを持っているとしましょう。ユーザーが自分のプロフィールページを確認したのと同じ正確な時間に、自分のプロフィールページから200を1つ追加し、10人のユーザーが同時にログインすると200 + 1 = 201になります。データベースはどのように動作しますか?mysqlの現在の値に数値を追加するには(同時に複数回)?

論理的には、ユーザがプロファイルをチェックした時刻が200だったので、1回の訪問でカウントされるため、MYSQLのアップデートが発生したときは常に201になります。

答えて

17

既存のポイント数を選択する場合は、クライアントに追加してから、更新された値をデータベースに書き戻してから、race conditionになります。あなたが指摘しているように、一部のビューはカウントされない可能性があります。

代わりに、アトミック更新を使用しようと、問題を回避する必要があります。

UPDATE user SET points = points + 1 WHERE id = 42 

代替はSELECT ... FOR UPDATEを読むことです。 documentationから:あなたはページ・ロックまたはロー・ロックを使用するストレージエンジンとFOR UPDATEを使用

場合、クエリによって調べた行は、現在のトランザクションが終了するまで書き込みロックされています。 LOCK IN SHARE MODEを使用すると共有ロックが設定され、他のトランザクションで検査済みの行を読み取ることはできますが、更新や削除はできません。第14.2.8.3項「共有モードでのSELECT ... FOR UPDATEおよびSELECT ... LOCKのロックの読み取り」を参照してください。

関連する問題