我在PHP中有这个彩票游戏。它非常简单,它由三个表组成:
awards:
- ID
- award_name
wingames:
- ID
- ID_award
allgames:
- ID_user
- won_game (bool)
- award_id (if game not won, then it is 0)
宣布,例如,比赛开始时间下午18:00。大约100名用户经常点击“尝试赢”。管理员有时会在表格中插入一个奖励ID,以便下次点击用户赢得此项目。
此按钮执行以下操作: 从wingames限制1中选择id_award; - 如果没有行 - 用户输掉游戏,则进行以下查询: 插入allgames(id_user,won_game,award_id)值(43,false,0); - 如果有一行 - 用户赢得游戏,软件会进行以下两个查询: 插入allgames(id_user,won_game,award_id)值(43,true,5); 从wingames删除;
有一个问题:在“从wingames删除”查询执行之前,另一个用户从该表中读取,他有一个奖励。因此,当2个用户同时点击按钮时,可能会发生(并且已经发生),有两个赢家而不是一个。这是一个很大的问题,因为我必须给两个奖品而不是一个。
我在互联网上查了一些“锁定表”的解决方法,但没有找到合适的例子。
你有任何(可能快速和肮脏)的解决方案吗?
答案 0 :(得分:0)
正如zerkms所提到的,你需要SELECT .. FOR UPDATE。它将锁定游戏直到您的交易结束。
START TRANSACTION;
SELECT * FROM wingames FOR UPDATE;
/* from now on, only one request can continue, the others are blocked */
INSERT INTO allgames ...
DELETE FROM wingames WHERE ID = ...
COMMIT;
您应该在两个交互式客户端上尝试此操作,以查看FOR UPDATE语句的工作原理。