你会如何构建这个php-mysql查询?

时间:2012-03-12 12:03:38

标签: php mysql

当玩家选择与随机对手玩时,我正在制作一个基于回合的游戏,并试图构建匹配功能。当谈到mysql时,我是一个菜鸟,所以我需要一些帮助。

我在考虑这样做:

  1. 当玩家选择对抗随机对手时,请检查“waiting_list”表以查看是否有任何对手。

  2. 如果没有对手,请将玩家添加到等候名单中。

  3. 等候名单上有一个对手,从列表中移除玩家,然后与其他玩家一起开始游戏。

  4. 我担心的是,如果我这样做的话,等待名单上的同一名球员是否有机会被几名球员选中。想象一下,如果有100,000名玩家选择了自动匹配功能,那么数据库(phpmyadmin)是否能够很好地处理它?你会如何构建逻辑?

    谢谢

2 个答案:

答案 0 :(得分:3)

  

我担心的是,如果我这样做的话,等待名单上的同一名球员是否有机会被几名球员选中。

你用你的观点描述的内容1.)到3.)是一个所谓的商业交易,你在这里有一个原子操作,只能由一个玩家同时执行。

您应该将操作封装到处理它的对象中,因此您的业务逻辑中有一个接口来执行该事务。

然后你需要实现这个交易。事务可以成功或失败,您可以使用返回值或异常处理失败。

交易本身必须确保您的顾虑被删除。这可以通过独占锁定匹配表,进行匹配,删除或将播放器/操作符添加到等待列表并释放锁定来在MySQL中完成。

请参阅12.3.5. LOCK TABLES and UNLOCK TABLES Syntax­Docs

表锁具有性能影响,因为只要表被锁定,其他会话就无法访问它(等待锁被释放)。

因此,保持锁定时间短是明智的。如果事务需要10毫秒,您可以将它与并发活动事务的数量相乘,以便及时表达您的性能:

0.010 seconds * 100 000 transactions = ~ 16.7 minutes

请注意,您不可能拥有10万个并发交易,因为并非所有玩家都会立即匹配。但是,您需要跟踪数字,因为系统可能会在一段时间后停止。

答案 1 :(得分:1)

为了防止单个玩家进入多个游戏,您可以使用“GameIDAssigned”的附加列(如果不存在)进行等待列表,默认为0(或者甚至是PlayAgainstPerson)。

在查询可用于并向许多玩家显示的数据时,记录可能都具有相似的时间戳,但您只需要1.因此,以随机方法选择一个,然后将ID分配给等于时间戳的ID没有分配游戏。如果它回来了1条记录被更新,那就是你的。如果它被分配给其他人,则GameIDAssigned将被填写,从而阻止您第二次分配它。比如...

PersonIDFromWaitingList = SomeValueEvenIfBySQLSubSelect

Update YourWaitingListTable
   set GameIDAssigned = SomeCurrentGameIDSequence
   where DateTimeStampColumn = ValueWhenOriginallyQueried
     AND GameIDAssigned = 0

在没有看到任何其他关于你的游戏结构或表格列的元素的情况下,我现在可以提供更多的内容,但希望你能够得到这个想法。如果一个等待名单的人被同时由多个人分配,则只有第一个获得更新完成的人(当游戏ID分配仍为0时)获胜并且其他所有人试图获得该人将会错过并需要尝试下一个可用...