同时运行多个PHP脚本(数据库循环问题)

3

我在Linux系统上同时运行了10个PHP脚本,并且它们正在后台处理。

例如:

while ($i <=10) {
 exec("/usr/bin/php-cli run-process.php > /dev/null 2>&1 & echo $!");
 sleep(10);
 $i++;
}

run-process.php中,我遇到了数据库循环的问题。可能已经有一个进程将status字段更新为1,但似乎其他php脚本进程没有看到它。例如:
$SQL = "SELECT * FROM data WHERE status = 0";
$query = $db->prepare($SQL);
$query->execute();

while ($row = $query->fetch(PDO::FETCH_ASSOC)) {
    $SQL2 = "SELECT status from data WHERE number = " . $row['number'];
    $qCheckAgain = $db->prepare($SQL2);
    $qCheckAgain->execute();
    $tempRow = $qCheckAgain->fetch(PDO::FETCH_ASSOC);

    //already updated from other processs?
    if ($tempRow['status'] == 1) {
        continue;
    }

    doCheck($row)
    sleep(2)
}

如何确保进程不会再次处理相同的数据?


尝试使用MySQL事务。 示例:https://dev59.com/GHE85IYBdhLWcg3wkkjK - Vladimir Posvistelik
顺便提一下,如果您的查询没有任何参数,调用 prepare() 只会增加不必要的开销。相反,您可以使用 $db->exec($SQL); - Michael Mior
4个回答

3
当你有多个进程时,需要每个进程拥有一定数量的记录。通常通过使用带有限制条件的更新来实现此操作,然后选择刚刚被脚本“拥有”的记录。
例如,可以设置一个字段来指定记录是否可用于处理(即值为0表示可用)。然后,您的更新将该字段的值设置为脚本进程ID或某个其他唯一数字到进程。然后您可以根据进程ID进行选择。当处理完成后,您可以将其设置为“已完成”数字,例如1。更新、选择、更新、重复。

我不确定你所说的“带有限制子句的更新”是什么意思?所以你的意思基本上是,我可以添加一个名为run_by的字段,其值将为Robot-ARobot-BRobot-C - 前10,000行将用于由Robot-A进行处理? - I'll-Be-Back
是的。因此,您的查询将是UPDATE table SET run_by="ROBOT-A" WHERE run_by="UNPROCESSED" LIMIT 10,000. 然后SELECT * FROM table WHERE run_by="ROBOT-A"。然后处理完成时UPDATE table SET run_by="PROCESSED" WHERE run_by="ROBOT-A"。MySQL会处理记录的争用问题。如果使用InnoDB,则需要在UPDATE之前发出LOCK TABLE(然后解锁)。 - Brent Baisley

1
你的脚本多次执行相同的查询语句是因为你创建了并行处理。进程1从数据库中读取数据,进程2也从数据库中读取数据,然后两个进程开始处理它们的数据。
为了消除这种竞争条件,数据库提供了事务处理。看一下PDO 提供的处理数据库事务的方法。

我已经使用了第二个 SQL 查询来解决竞态条件 - 它会检查 status = 1,然后跳过它。我将研究数据库事务,谢谢。当更新 status 为 1 时,我需要添加数据库事务吗?这发生在 doCheck($row) 函数中(请参见我的问题)。 - I'll-Be-Back
我刚刚阅读了关于数据库事务的内容,如果我理解正确,那么在 while 循环之前需要添加 beginTransaction(),在 while 循环内部需要添加 commit() 吗? - I'll-Be-Back

1

我不完全确定你正在处理的方式/内容。

您可以引入限制子句并将其作为参数传递。因此,第一个进程处理前10个,第二个进程处理接下来的10个,依此类推。


我在“数据”表中有超过100,000行 - 如何计算每个进程的限制?假设有10个进程。 - I'll-Be-Back

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接