For a browser game, I have a database table fights:
- fightID
- fromID
- toID
- simulated (1=true, 0=false)
Whenever a user requests a page, I select all fights which still have to be simulated:
SELECT fightID, fromID, toID FROM fights WHERE simulated = 0
These outstanding fights are then simulated in the PHP script and, finally, the fight is marked as simulated and the winner gets his points:
UPDATE fights SET simulated = 1 WHERE fightID = X
UPDATE users SET points = points+1 WHERE userID = WINNER
The problem:
Imagine two users coming to the page one after another in only a few milliseconds. On both users’s page load the same outstanding fights are selected. Then they are simulated and – since both requested the page almost at the same time – the winner gets his points twice. The fights are then marked as simulated. But this is too late.
How can I avoid this problem? Thank you very much!
If you are sure that once you read the fights from the DB, they will be simulated (i.e. it is not possible that the user quits and that some fights are left unsimulated), you an use a transaction to read and update the fights in one, atomic operation.
and then later update the scores.