情况:我创建了一个cron作业。这是为了将客户输入的订单添加到API。我将它设置为每隔一分钟运行一次。
问题:有时,当有太多挂单时,第二个cron作业在第一个结束之前被调用。这导致通过API发送重复订单。
解决方案:我在数据库中创建了一个名为cron_jobs的表。它有两列,ID和状态。当cron作业运行时,它会检查状态是否为0。如果status为0,则将状态更新为1.它完成其进程并再次将状态标记为0.如果作业的状态为1(表示它已在运行),并且再次命中,则操作为终止。
意外麻烦:此解决方案似乎在逻辑上是正确的。但是当我实施它时,结果令人震惊。作业运行时,其状态将更新。但是当再次调用它时,数据库仍然返回状态0并继续执行。我也使用了睡眠方法,以便我有足够的时间来研究这个问题。但是数据库总是返回不正确的值,而不是我使用phpmyadmin看到的值。
请不要认为我可能犯了一些愚蠢的错误。 在完全调用第一个实例之前,文件的第二个实例始终提取不正确的值。 看看我的代码:
<?php
$Output = mysql_fetch_assoc(mysql_query("select status from jobs where ID='1'"));
if($Output['status'] == '0')
{
mysql_fetch_assoc(mysql_query("update jobs set status='1' where ID = '1'"));
mysql_fetch_assoc(mysql_query("update jobs set invoked = invoked+1 where ID = '1'"));
echo 'Executed';
}
else
{
echo 'Error: Another cron job already in process. Operation terminated!';
die();
}
/*I perform some lengthy tasks here*/
/*Sleep function called to check whether another instance of the program works while this one is in progress */
sleep(60);
/*Task is complete. We are marking 0 as status so that another instance is allowed to work on.*/
mysql_fetch_assoc(mysql_query("update jobs set status='0' where ID = '1'"));
?>
观察1 :如果我在另一台浏览器或另一台计算机上运行第二个实例,它会完美运行。
观察2 :我试图调查是否实际上被调用了几次。我在表中创建了另一列“No_Of_Times_Invoked”。我发现当我从同一个浏览器使用时,代码实际上失败了。
答案 0 :(得分:1)
您的SELECT
查询使用表格cron_jobs
。每个其他查询都使用jobs
。我相信您的SELECT
查询失败,导致mysql_query()
返回false
。
$Output = mysql_fetch_assoc(mysql_query("select status from cron_jobs where ID='1'"));
由于mysql_query()
在此处返回false
,mysql_fetch_assoc()
也会返回false
。
if($Output['status'] == '0')
$Output
是false
。在PHP中,使用==
时,可以进行类型转换。在这种情况下,$Output['status'] == '0'
评估为true
。 (请注意,$Output['status']
为null
,但null == '0'
评估为false
。type juggling和loose comparisons的欢乐。)
用
替换您的查询SELECT `status` FROM jobs WHERE ID = '1'
它应该运行正常。
我建议在mysql_*()
函数的返回值中添加一些错误检查(使用$returnValue === false
),或者更好的是,切换到PDO。
在评论中进行了一些讨论后更新
问题似乎是您正在使用浏览器进行测试。至少Firefox 23.0.1(我用于测试)在第一个请求完成之前不发送第二个请求。这可以解释您所看到的所有行为。新的浏览器或计算机将无法重新使用连接,因此在这种情况下它可以正常工作。
如果我从命令行启动脚本两次(相隔五秒),它就能正常工作:第二次运行输出Error: Another cron job already in process. Operation terminated!
。
请注意,PHP确实会抱怨每个mysql_fetch_assoc()
函数调用周围的mysql_query("update ...")
无效:
警告:mysql_fetch_assoc()要求参数1为资源,第7行的/test/test.php中给出布尔值