2009-06-18 58 views
5

我承认我不是100%的PDO和MySQL的内部工作,所以我会举一个例子让我的问题更清晰。有没有办法迫使PHP等待MySQL完成事务处理?

我正在制作一个相当粗糙的基于浏览器的战略游戏,因为我认为这是学习PHP和数据库的有趣方式。当我遇到一个意想不到的错误时,我正在测试战斗脚本。我使用Cron Jobs每分钟调用脚本,看起来像这样:

$ sql =“SELECT army_id FROM activearmy WHERE arrival = 0;”;

foreach($dbh->query($sql) as $row) 
    { 

     battleEngine($row["army_id"]); 

    } 

当基本的计算完成(进攻的军队保卫主场迎战军队),数据库中的六个表进行更新。我面临的问题是,当我在同一分钟内对同一个目标进行多次攻击时,其中一次或一次攻击会获取过时的数据库信息(在极端情况下,攻击#10获取与攻击5相同的表) 。

我猜这是因为脚本比数据库更快?有没有一种方法可以强制PHP等到所有相关信息都到位之后再用下一个$行重复该函数?

编辑:埃米尔可能是正确的。我无法确定,因为我的PDO似乎不可能保持足够长的时间,以便在beginTransaction()和commit()之间传递几条语句。然而,由于我使用InnoDB和“REPEATABLE READ”,脏读看起来很奇怪。一些谷歌搜索建议REPEATABLE READ将使脏读不可能。在考虑如何自杀一段时间之后,我选择了黑客。现在,我在我的脚本上放置了一个特殊值的UPDATE,另一个放在底部的大批量(大约6个UPDATE语句)的末尾。在运行该函数之前,我已经建立了一个while() - 循环来检查特殊值是否被设置为0.如果不是,它会休眠0.01秒,然后再试一次。看着输出,while循环平均重复两次,表明它可能实际上在工作?它还没有失败,但可能是因为它不是高峰时段。我明天定期再试一次。我知道没有人关心这一切,但我觉得我应该做这个更新以防万一。 = P

回答

1

如果PHP只是完全等待,那么您会得到大量的cron作业。

你想要什么想要使用类似于anachron的东西,以确保在任何给定时刻只有一个脚本实例运行。您也可以执行以下操作:

<?php 

    if (file_exists('/tmp/myscriptlock')) exit(); 
    touch('/tmp/myscriptlock'); 

    // do your stuff 

    unlink('/tmp/myscriptlock'); 
+0

srry为格式不好 – Evert 2009-06-18 23:04:18

+1

这将是更好的使用MySQL锁,这样,如果作业,从而连接死亡锁自动释放。 http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_get-lock – 2009-06-18 23:06:44

1

您所看到的内容称为“脏读”。使用InnoDB并将isolation level设置为可序列化。然后将所有查询包含在事务块中:

$dbh->beginTransaction(); 
// run queries 
$dbh->commit();