2011-11-20 19 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++; 
} 

、私はデータベースループに問題を抱えています。 1つのプロセスが既に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

複数のプロセスがある場合は、各プロセスに特定のレコードセットの「所有権」を持たせる必要があります。通常、これを行うには、limit句を指定して更新を行い、スクリプトによって「所有」されたレコードを選択します。

たとえば、レコードが処理可能かどうかを指定するフィールドがあります(値が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"。その後、処理が完了すると、SET UPDATE SET SET run_by = "PROCESSED" WHERE run_by = "ROBOT-A"となります。 MySQLはレコードの競合問題を処理します。 InnoDBを使用している場合は、UPDATEの前にLOCK TABLEを発行してから、ロックを解除する必要があります。 –

1

スクリプトが同じクエリを複数回実行する理由は、作成している並列化が原因です。プロセス1はデータベースから読み取り、プロセス2はデータベースから読み取り、両方がデータの処理を開始します。

データベースは、このような競合状態を解消するためにトランザクションを提供します。どのようなPDOprovidesデータベーストランザクションを処理するために見てみましょう。

+0

を使用することができます。競合状態のように2番目のsqlクエリを使用しました。 'status = 1'をチェックしてスキップします。私はデータベーストランザクションを調べます。ありがとうございます。 'status'を1に更新するときにデータベーストランザクションを追加する必要がありますか? –

+0

正しく理解すれば、whileループの前にbeginTransaction()を追加し、whileループにcommit()を追加する必要がありますか? –

1

どのように処理しているかわからないです。

limit句を導入し、それをパラメータとして渡すことができます。したがって、最初のプロセスは最初の10回、2回目のプロセスは次の10回などを行います。

+0

私は 'data'テーブルに100,000以上の行を持っています - 各プロセスの制限をどのように計算するのですか? 10のプロセスを言いましょう。 –

関連する問題