Я одновременно запускаю 10 PHP-скриптов и обрабатываю их в фоновом режиме на Linux.
Например:
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) }
Как я могу обеспечить, чтобы процессы не повторяли повторные повторные данные?
Когда у вас есть несколько процессов, вам необходимо, чтобы каждый процесс принимал «право собственности» на определенный набор записей. Обычно вы делаете это, выполняя обновление с предложением limit, а затем выбираете записи, которые были просто «принадлежат» скрипту.
Например, укажите поле, которое указывает, доступна ли запись для обработки (т.е. значение 0 означает, что оно доступно). Затем ваше обновление установит значение поля идентификатору процесса сценариев или другому уникальному номеру процесса. Затем вы выбираете идентификатор процесса. Когда вы закончите обработку, вы можете установить ее на «законченный» номер, например 1. Обновить, Выбрать, Обновить, повторить.
Причина, по которой ваш сценарий выполняет один и тот же запрос несколько раз, объясняется созданием параллелизма. Процесс 1 читает из базы данных, процесс 2 читает из базы данных и начинает обработку своих данных.
Базы данных обеспечивают транзакции, чтобы избавиться от таких условий гонки. Посмотрите, что PDO
обеспечивает обработку транзакций базы данных.
я не совсем уверен, как / что вы обрабатываете.
Вы можете ввести предложение limit и передать это как параметр. Таким образом, первый процесс выполняется сначала 10, второй – следующие 10 и так далее.
вам нужен замок, например «SELECT … FOR UPDATE».
innodb поддерживает блокировку уровня строки.
см. http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html .