我目前正在使用以下规则制作即时赢奖游戏:第一个用户在最后一个获胜后至少半小时注册。因此用户可以每半小时赢一次。如果没有人在几个小时内注册,那么第一个注册胜利。
服务器使用PHP 5.2.0,这解释了我不使用DateTime类。我的表格是InnoDB。
我的脚本的这一部分在用户注册时由每个客户调用,并决定用户是否获胜:
$currentTime = date("Y-m-d H:i:s");
// We're looking for the last winner in the winners table
$res = $dbh->query("SELECT date FROM winnertable ORDER BY id DESC")->fetch(PDO::FETCH_ASSOC);
if(empty($res)){
// If there is no last winner then the user wins
$winner = true;
}else{
// If there is already a last winner, we check the date of win, if superior to half an hour, the user wins
if(strtotime($currentTime)-strtotime($res["date"])>=1800){
// Last winner was half an hour ago : winner
$winner = true;
}
}
// if the winner flag is set to true, add the user id to the winners table along with the date of winning
if($winner){
$dbh->query("INSERT INTO winnertable (id_main, date) VALUES ('".$_SESSION['id']."', '".$currentTime."')");
}
下一页必须向用户显示结果,以便他知道他是否赢了。所以我事后无法做出CRON工作。
这个脚本存在缺陷,因为如果多个客户端在同一时间访问它,它可能会使多个客户端获胜。
我已经阅读了一些解决方案:
答案 0 :(得分:0)
你可以做的是为这种情况增加一个阶段,你有另一个临时表来存储“潜在的”赢家 - 那些满足获胜标准的人。然后在其上运行SELECT作为按日期排序的辅助操作,索引按升序排列,限制为1。获取该值并将其添加到真正的获胜者表中,并将其用作下一次获胜计算的基础,并清除临时表。那样你应该只获得一个胜利者。它当然会增加开销,但它只会每半个小时发生一次,所以我认为这不应该是一个问题。
答案 1 :(得分:0)
我最终决定以不同的方式思考问题并决定发布解决方案,因为它可能对某些人有所帮助。
我已经阅读了InnoDB表行级别锁并执行了以下操作:
Stmt#1:UPDATE winnertable SET id_main = [id] WHERE date_add(next_date,INTERVAL X SECOND)<现在()和id_main = 0
如果PDO返回修改后的行($ stmt-> rowCount()),那么它就是胜利者,你必须在winnertable中为下一个获胜者插入一个新行:
Stmt#2(有条件的):INSERT INTO winnertable SET next_date = NOW()
感谢您的帮助!