PHP / MySQL: быстрое предотвращение повторяющихся действий - PullRequest
0 голосов
/ 23 февраля 2010

Для браузерной игры у меня есть таблица базы данных Борьба :

  • fightID
  • fromID
  • toID
  • смоделировано (1 = истина, 0 = ложь)

Всякий раз, когда пользователь запрашивает страницу, я выбираю все бои, которые еще должны быть смоделированы :

SELECT fightID, fromID, toID FROM fights WHERE simulated = 0

Эти выдающиеся бои затем моделируются в скрипте PHP и, наконец, бой помечается как имитированный, и победитель получает свои очки :

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

Проблема :

Представьте, как два пользователя приходят на страницу один за другим всего за несколько миллисекунд. На странице загрузки обоих пользователей выбираются одинаковые выдающиеся бои. Затем они моделируются и - поскольку оба запрашивают страницу почти одновременно - победитель получает свои очки дважды. Бои затем помечены как смоделированные. Но это слишком поздно.

Как мне избежать этой проблемы? Большое спасибо!

Ответы [ 3 ]

3 голосов
/ 23 февраля 2010

Если вы уверены, что после прочтения боев из БД они будут смоделированы (т. Е. Пользователь не сможет выйти и некоторые бои останутся не имитированными), вы используете транзакция читать и обновлять бои за одну атомарную операцию.

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

, а затем обновите результаты.

0 голосов
/ 23 февраля 2010

Хм, а что если вы используете 3 состояния симуляции? 0 = не моделируется, 1 = моделируется СЕЙЧАС, 2 = моделируется. Затем вы можете пометить симуляцию сразу после того, как пользователь загрузит бой.

0 голосов
/ 23 февраля 2010

Вместо сохранения баллов в таблице пользователей вы можете создать таблицу «победителей»

userId
fightId
...

и (userId, fightId) будет первичным ключом. Это помешает любому пользователю получить более 1 (или что-то еще) очков за бой. Очки будут рассчитаны по select count(*) from winners where userId=?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...