2017-05-03 24 views
0

私はphpスクリプトを実行する必要があります。同時に実行するスクリプトは複数ありません。mysqlデータベースを使用してシングルスレッドジョブを管理する方法は?

私はMySQLを使用しています、と私もののについては、このソリューション:

は私が怒鳴るデータベース構築:私はランダムなタスクIDを作成するスクリプトを実行する前に

 job_id    | task_id | last_updated_time (AUTO UPDATE) 
    "sending_emails"    77238  2107-5-3 12:2:2 

を、そして私が更新するために、クエリを実行しますtask_id。

$task_id = generate_random_task_id(); 
    $query = " 
        UPDATE 
         jobs 
        SET 
         task_id = $task_id 
        WHERE 
         task_id = $task_id 
         OR 
         NOW() - last_updated_time > 30 
        LIMIT 1 
      " 

/* 
    Then I need to check if there was an update, if yes then I will run the script otherwise i will stop since there is already another script running 
*/ 

$query = "SELECT JOB_ID WHERE taks_id = $task_id " 
$result = run($query) 
if(! isset($result[JOB_ID])){ 
    DIE(); 
} 

2つのスクリプトが同時に実行される可能性はありますか?

答えて

0

いいえ、彼らは同時に実行することはできません、here's MySQLのドキュメントを約UPDATESELECT、これはこう言われる、

UPDATE ... ...が排他ネクストキーを設定し、すべてのレコードにロック 検索の出会い。ただし、一意索引を使用して行をロックする文では、 の一意の行を検索するためには、索引レコードのロックのみが必要です( )。

Here's共有と排他ロックの詳細

は:

共有(S)ロックが 行を読み取るためにロックを保持するトランザクションを可能にします。

排他的(X)ロックは、ロックを保持しているトランザクションに 行の更新または削除を許可します。

トランザクションT1が行rに排他(X)ロックを保持している場合、いずれかのタイプのロックが特定のトランザクションT2からの要求 は、すぐに付与することはできません。代わりに、トランザクションT2は、 トランザクションT1が行rのロックを解放するのを待たなければなりません。

0

はい、同じタスクをもう一度実行する可能性があります。

2つの明白な解決策があります。

1つは、mysql接続を開き、短いタイムアウトを使用してGET_LOCK()を使用してロックを取得することです。ロックを取得すると、あなたはうまく行きます。スクリプトの存続期間中、db接続を維持する必要があります。

また、finish_timeに一意の制約を持つテーブルを作成し、開始時刻を示す終了時刻がnullのレコードをINSERTします(終了時刻がnullのレコードがすでに存在する場合は失敗します)。完了したらNOW()。

実行中のタスクの状態を表すためにデータベースを使用することは、結合されているが可用性の高いクラスタ内でタスクが実行されている場合のみ意味を持ちます。つまり、データベースもクラスタ化されていることを意味します。また、クラスタリング(NDB、asych、セミシンク、マルチマスター)の性質は、これがどのように実際に動作するかに多くの影響を与えます。

OTOHそうでない場合、状態を表すためにデータベースを使用することは、問題を解決するための間違った方法です。

+0

ありがとうございますが、なぜfinish_timeが機能するのか分かりませんし、私の仕事はうまくいかないでしょうか? –

+0

@ダルシャン・メフタの答えをご覧ください。 –

+0

間隔を指定せずにSQLで時間通りに計算を行うという複雑さを除けば、実行が30秒未満で済むことが保証できる場合にのみ目的が達成されます。また、データベースの並行性モデルによって競合状態が発生します。さらに、あなたの例では、あなたのタスクIDの生成には非常に低いエントロピーしかありません。もしこれを高い頻度で実行しているのであれば、ある時点で衝突することになります。私は行く必要がありますか? – symcbean

0

はい、同時に実行できます。 あなたがそれらは、一度に1つを実行したい場合はSELECT クエリは次のように変更します。この場合

SELECT JOB_ID WHERE taks_id = $task_id LOCK IN SHARED MODE 

それは読み込みロックを使用しています。

NDBとInnoDBのどちらを使用するかは同じです。

関連する問題