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

问题描述:

我在同一时间运行10个PHP脚本,并在Linux上在后台处理它。同时运行多个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) 
} 

如何确保程序不被再次重复做相同的数据?

+0

尝试使用mysql事务。 示例:http://*.com/questions/2708237/php-mysql-transactions-examples –

+0

另外,如果你的查询没有任何参数,调用'prepare()'只会增加不必要的开销。相反,你可以使用'$ db-> exec($ SQL);' –

当您有多个进程时,您需要让每个进程都拥有某组记录的“所有权”。通常,您通过使用限制条款进行更新来完成此操作,然后选择脚本仅“拥有”的记录。

例如,有一个指定记录是否可用于处理的字段(即值为0表示它可用)。然后,您的更新会将该字段的值设置为脚本进程标识或进程的其他唯一编号。然后你选择进程ID。完成处理后,可以将其设置为“已完成”编号,例如1.更新,选择,更新,重复。

+0

我不确定“限制条款更新”是什么意思?所以基本上你的意思是我可以添加一个名为'run_by'的字段,其值将是'Robot-A','Robot-B','Robot-C' - 前10,000行将用于'Robot-A'处理? –

+0

是的。所以你的查询将是UPDATE表SET SET RUN_BY =“ROBOT-A”WHERE run_by =“UNPROCESSED”LIMIT 10,000。SELECT * FROM表WHERE run_by =“ROBOT-A”。然后当处理完成UPDATE表SET SET run_by =“PROCESSED”WHERE run_by =“ROBOT-A”。 MySQL处理记录的争用问题。如果使用InnoDB,则需要在UPDATE(然后解锁)之前发出LOCK TABLE。 –

您的脚本多次执行相同查询的原因是您正在创建的并行化。进程1从数据库中读取,进程2从数据库中读取数据,并开始处理其数据。

数据库提供交易以摆脱这种竞争条件。看看用于处理数据库事务的是什么PDOprovides

+0

我已经使用了第二个sql查询来处理竞争条件 - 它检查'status = 1'是否跳过它。我会研究数据库事务,谢谢。更新'status'为1时是否需要添加数据库事务?这发生在'doCheck($ row)'函数中(请参阅我的问题) –

+0

我刚刚阅读了数据库事务,如果我理解正确,是否需要在while循环前添加beginTransaction(),并在while循环中添加commit()? –

我不完全确定你正在处理的是/如何。

您可以引入限制条款并将其作为参数传递。所以第一个过程先做10,第二个过程做下一个10,等等。

+0

我在'data'表中有超过100,000行 - 如何计算每个进程的限制?让我们说10个进程。 –

您需要锁定,如“SELECT ... FOR UPDATE”。

innodb支持行级锁。

有关详细信息,请参阅http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html