PHP / MySQL: arkaya hızla yinelenen eylemleri önleme

3 Cevap php

Bir tarayıcı oyunu için, ben bir veritabanı tablo var fights:

  • fightID
  • fromID
  • söyledim
  • simüle (1 = true, 0 = false)

Bir kullanıcı bir sayfa istediğinde, ben select all fights which still have to be simulated:

SELECT fightID, fromID, söyledim FROM fights WHERE simulated = 0

Bu olağanüstü kavgalar daha sonra PHP komut simüle ve, nihayet, the fight is marked as simulated and the winner gets his points edilir:

UPDATE fights SET simulated = 1 WHERE fightID = X
UPDATE users SET points = points+1 WHERE userID = WINNER

The problem:

Sadece birkaç milisaniye içinde sayfanın birbiri ardına gelen iki kullanıcılara düşünün. Hem kullanıcıların en sayfa yük aynı üstün kavgalar seçilir. Sonra simüle edilir ve - her ikisi de hemen hemen aynı anda sayfasını istenen beri - kazanan iki kez yaptığı puan alır. Kavgalar simüle gibi then işaretlenmiş. Ama bu çok geç.

How can I avoid this problem? Thank you very much!

3 Cevap

Eğer DB kavgalar kez okumak, onlar size bir kullanım a transaction, okumak ve (yani kullanıcı çıkar ve bazı kavgalar unsimulated kaldığını bu mümkün değil) simüle edilecek eminseniz biri, atomik işlem kavgalar güncelleyin.

START TRANSACTION;
SELECT fightID, fromID, toID FROM fights WHERE simulated = 0
UPDATE fights SET simulated = 1 WHERE fightID = X
COMMIT;

ve daha sonra puanları güncelleyin.

Bunun yerine, kullanıcıların tablodaki puan keepeng size bir 'kazanan' tablo oluşturabilirsiniz

userId
fightId
...

ve (kullanıcı kimliği, fightId) birincil anahtar olacaktır. Kavgada başına en fazla 1 (ya da herneyse) puan geting herhangi bir kullanıcı önleyecektir. Noktaları select count(*) from winners where userId=? hesaplanır olacaktır

Hmm, bunu simülasyon 3 devletler ne kullanırsanız? 0 = simüle = 1 = ŞİMDİ 2 taklit, taklit değil. Sonra kullanıcı kavga yükler hemen sonra bayrak simülasyon yapabilirsiniz.