PHP/MySQL : Preventing duplicate actions quickly in succession

标签 php mysql database time

对于一个浏览器游戏,我有一个数据库表战斗:

  • 战斗ID
  • 发件人ID
  • 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

问题:

想象一下两个用户在短短几毫秒内陆续访问该页面。在两个用户的页面加载上,都会选择相同的出色战斗。然后对它们进行模拟,并且由于几乎同时请求该页面,获胜者将获得两次积分。战斗然后被标记为模拟。但这已经太迟了。

如何避免这个问题?非常感谢!

最佳答案

如果您确定一旦您从数据库中读取了战斗,它们就会被模拟(即用户不可能退出并且某些战斗不会被模拟),您可以使用 a transaction通过一次原子操作读取和更新战斗。

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

然后更新分数。

关于PHP/MySQL : Preventing duplicate actions quickly in succession,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2319787/

相关文章:

java - 如何更新 ListView 中的记录以及android中的数据库

php - 在 PHP5 的 _destruct 中自动取消设置所有类变量

mysql - 连接派生表时列不能为空错误

sql - 在 VB NET 中从 SQL 数据库中检索位列

c# - 执行大量并发 INSERT 时如何避免 "Violation of UNIQUE KEY constraint"

python - 将数据库数据从 DEV 移动到 PRODUCTION,最佳实践?

php - 制作在线词典的最佳方法?

php - 需要在 iframe 加载时运行 sql 命令。最好不要使用 onload()

php - 将数据从表单传递到 Controller Laravel 5

mysql - 如何转换和修复 codeigniter 的此查询?