我正在使用Flash和PHP构建一个回合制的多人游戏。有时两个用户可能同时调用相同的PHP脚本。此脚本旨在将一些信息写入数据库。但是,如果该信息已由其他用户编写,则该脚本不应运行,否则游戏将中断。如果PHP按顺序处理这些脚本(类似于MySQL排队多个查询的方式),那么总共只能运行一个脚本,一切都应该没问题。
但是,我发现大约10%的时间都会执行两个用户的脚本。我的理论是,服务器有时会同时接收用户运行脚本的请求,并且它们都运行,因为它们都没有检测到任何已写入数据库的内容。两个脚本是否可能同时执行?如果是这样,这个问题的可能解决方案是什么。
答案 0 :(得分:1)
这确实是可能的。您可以尝试在脚本的开头和结尾锁定和解锁表。
虽然这会减慢一些请求,因为他们必须先等待锁定的表被解锁。
答案 1 :(得分:0)
他们这样做是非常合理的。查看database transactions。
简而言之,数据库事务用于控制同时访问数据库的程序之间的并发性。您启动一个事务,然后执行多个查询,最后提交事务。如果两个脚本相互重叠,则其中一个脚本将失败。
请注意,隔离级别可以进一步细化控制两个(或更多)竞争脚本可以共享的程度。通常允许所有数据库都准备就绪,但只允许一个写入。因此错误将在最终提交时发生。只要数据库中出现所有副作用,这都很好,但如果您有外部副作用(例如删除文件或发送电子邮件),则不够。在这些情况下,您可能需要在交易期间lock a table或row或设置isolation level。
答案 2 :(得分:0)
没关系,如果它是PHP,C,Java那么。同时,运行 max只需要与CPU(和核心)一样多的进程。如果你只有2个核心,可以同时运行让100个进程同时运行。只有2个正在运行,其余的正在等待。
现在它取决于您在运行下看到的内容。如果您将其视为活动状态或者您也采取等待进程。其次,它取决于您的系统配置,可等待的进程数和系统规格。
答案 3 :(得分:0)
这是一个可以使用的SQL表锁定示例,以便首先抓取数据库的第一个PHP线程将锁定表(使用锁名称“awesome_lock_row”),直到它最终释放它。第二个线程尝试使用同一个表,并且由于锁名称也是“awesome_lock_row”),它会一直等到第一个PHP线程解锁表。
对于此示例,您可以尝试同时运行相同的脚本100次作为cron作业,您应该看到“update_this_data”数字字段增量为100.如果表未被锁定,则所有并发的100个线程将可能首先将“update_this_data”同时视为0,最终结果只是1而不是100.
<?php
$db = new mysqli( 'host', 'username', 'password', 'dbname');
// Lock the table
$db->query( "DO GET_LOCK('awesome_lock_row', 30)" ); // Timeout 30 seconds
$result = $db->query( "SELECT * FROM table_name" );
if($result) {
if ( $row = $result->fetch_object() )
$output = $row;
$result->close();
}
$update_id = $output->some_id;
$db->query( UPDATE table_name SET update_this_data=update_this_data+1 WHERE id={$update_id} );
// Unlock the table
$db->query( "DO RELEASE_LOCK('awesome_lock_row')" );
?>
希望这有帮助。
答案 4 :(得分:0)
乍一看,声音听起来像是保持脚本第二个实例滚动的速度不够快,但有10%的时间...我知道您已经像某人一样拥有某种“锁”告诉你添加,这很棒。如上所述,请始终将此锁放在脚本中,即使在调用脚本之前也不要(在父脚本中也称为a)。竞争功能/对象等也是如此...
不过请注意,我是由Google指导的,我想找出的是,如果脚本A尚未完成运行,那么脚本B是否会在一个IFRAME中运行(如果需要,可以在“不同的窗口”中运行);基本上,您的标题有点模糊。非常感谢。
幸运的是,我们同在一条裤子:我正在使用php编写类似于《炉石传说》的纸牌游戏(我知道这根本不适合此游戏,但我只喜欢挑战性的任务,(好吧,那是我所熟悉的唯一语言))。基本上,我希望保留多个“即时”或动作,如果您希望在另一组全局事件/即时-即时-子即时正在滚动时触发。这包括永远不要在同一个滚动片段中调用一个有事件的函数,除非我在$ _SESSION变量上滚动一会儿,且该变量的值y仅会sleep(1)(发生在脚本A中);而$ _SESSION [“ phase”] ==“ EndOfTurnEffects”,然后继续滚动直到$ _SESSION [“ phase”] ==“ StandBy”(另一位玩家回合),我希望脚本B移动$ _SESSION [“ phase” ]。基本上,如果脚本B在执行脚本A之前没有运行,那么我会陷入while语句的无尽循环中……