我有一个填充了1000条记录的mysql数据库表,可以说是5000条记录.每条记录都有一个处理过的布尔标志,默认为false(0).我想做的是每分钟在cron上运行一个PHP脚本.它的代码是这样的:
<?PHP
process();
function process()
{
$sql = "SELECT id FROM items WHERE processed = '0' ORDER BY id ASC LIMIT 1";
$result = $this->db->query($sql);
if (! $result->has_rows())
die;
$id = $result->getSingle('id');
processItem($id); //Will set processed to 1 after processing is done
process();
}
?>
应该很清楚上面的代码是做什么的,它获取未处理的下一条记录的id,处理它,然后再次调用process()函数,重复这个过程,直到没有更多的项目要处理,此时执行将停止.
通过将此脚本放在Cron上以便每分钟运行一次,我希望此脚本的多个实例都能同时处理项目,因此,不是一次处理一个项目,而是可以同时处理5-10个项目.
1)这是否按照我计划的方式工作?有任何改进建议/需要注意的事项吗?
2)我是否应该让脚本为运行实例的数量设置一个计数器,因此每当cron作业启动时,它都会检查计数器,如果50(?)实例正在运行,它将退出而不进行处理.这可能会导致服务器因过多的运行进程占用太多内存而导致崩溃?有什么想法吗?
解决方法:
我有几件事要说:
首先,您使用递归来处理多行.如果你过于沉重,这可能会导致问题.而是使用一个简单的循环.
其次,您是否知道此代码是否可以从多次运行中受益?如果机器受cpu限制,则可能无法从另一个线程中受益.我建议你手动检查多少线程效果最好.更多线程并不总是让事情变得更快,在某些情况下实际上可以减慢一切.
最后,我肯定会限制这些脚本可以同时运行的数量.这可以通过确保每个脚本运行不超过5分钟来实现.或者您可以保留活动脚本的数量,并确保它不超过您在我的第二个建议中确定的最大数量.
编辑:我已经添加了一些有关递归可能导致的问题的更多信息:
每次递归调用函数时,堆栈上都会使用额外的空间.此空间存储任何局部变量以及函数的地址(允许它在被调用函数退出时恢复状态).堆栈只有一个有限的空间,所以最终你的程序会因堆栈溢出而崩溃.尝试运行这个简单的程序:
function a($i) {
print $i . "\n";
a($i + 1);
}
a(0);
在我的系统上,它在608739次迭代后崩溃了PHP.在更复杂的功能中,这个数字可能要小得多.一个简单的循环没有这些开销,因此它没有这个问题.