2011-11-20 2 views
3

동시에 10 개의 PHP 스크립트를 실행 중이며 Linux의 백그라운드에서 처리합니다. 예를 들어동시에 여러 PHP 스크립트 실행 (데이터베이스 루프 문제)

다음 run-process.php에서

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

, 나는 데이터베이스 루프에 문제가 있습니다. 프로세스 중 하나가 이미 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://stackoverflow.com/questions/2708237/php-mysql-transactions-examples –

+0

쿼리에 매개 변수가없는 경우'prepare() '를 호출하면 불필요한 오버 헤드가 추가됩니다. 대신 $ db-> exec ($ SQL);을 사용할 수 있습니다. –

답변

3

여러 프로세스가있는 경우 각 프로세스가 특정 레코드 집합의 "소유권"을 가져야합니다. 일반적으로 제한 절을 사용하여 업데이트를 수행 한 다음 스크립트에서 "소유"한 레코드를 선택하여이 작업을 수행합니다.

예를 들어 레코드를 처리 할 수 ​​있는지 (즉, 값 0은 사용할 수 있음을 나타냄) 여부를 지정하는 필드가 있어야합니다. 그런 다음 업데이트로 필드의 값을 스크립트 프로세스 ID 또는 프로세스의 다른 고유 번호로 설정합니다. 그런 다음 프로세스 ID를 선택하십시오. 완료 처리가 끝나면 1과 같이 "완료"번호로 설정할 수 있습니다. 업데이트, 선택, 업데이트, 반복하십시오.

+0

"한계 조항으로 업데이트 하시겠습니까?"라는 것이 무슨 뜻인지 확신 할 수 없습니까? 그래서 기본적으로'run_by'와 같은 필드를 추가 할 수 있으며 값은'Robot-A','Robot-B','Robot-C'입니다. 처음 10,000 행은'Robot-A'를위한 것입니다. 방법? –

+0

예. 따라서 귀하의 쿼리는 UPDATE 테이블 SET run_by = "ROBOT-A"where run_by = "UNPROCESSED"LIMIT 10,000이 될 것입니다.SELECT * FROM 테이블 WHERE run_by = "ROBOT-A". 그런 다음 처리가 완료되면 테이블을 갱신하십시오. run_by = "PROCESSED"WHERE run_by = "ROBOT-A". MySQL은 레코드와의 충돌 문제를 처리합니다. InnoDB를 사용한다면 UPDATE (잠금 해제) 전에 LOCK TABLE을 실행해야합니다. –

1

스크립트가 동일한 쿼리를 여러 번 실행하는 이유는 작성중인 병렬 처리 때문입니다. 프로세스 1은 데이터베이스에서 프로세스 2를 읽고 프로세스는 데이터를 처리하기 시작합니다.

데이터베이스는 이러한 경쟁 조건을 제거하기 위해 트랜잭션을 제공합니다. 데이터베이스 트랜잭션 처리를 위해 PDOprovides을 살펴보십시오.

+0

경쟁 조건처럼 두 번째 SQL 쿼리를 사용했습니다. 'status = 1'인지 확인한 다음 건너 뜁니다. 나는 데이터베이스 트랜잭션을 살펴볼 것이다. 'status'를 1로 업데이트 할 때 데이터베이스 트랜잭션을 추가해야합니까? 그것은 doCheck ($ 행)'함수에서 발생합니다 (내 질문에) –

+0

올바르게 이해한다면 데이터베이스 트랜잭션을 읽었습니다. while 루프 전에 beginTransaction()을 추가하고 while 루프에서는 commit()을 추가해야합니까? –

1

처리 방법/내용을 잘 모릅니다.

limit 절을 도입하고이를 매개 변수로 전달할 수 있습니다. 그래서 첫 번째 프로세스는 처음 10 번, 두 번째 프로세스는 다음 10 번을 수행합니다.

+0

나는'data' 테이블에 100,000 개 이상의 행을 가지고 있습니다 - 각 프로세스의 한계를 계산하는 방법은 무엇입니까? 10 개의 프로세스라고합시다. –