こんにちは私はさまざまなプレーヤーがたとえば1時間または2時間続くことができるアクションをスケジュールするブラウザゲームを持っています。cronジョブは毎分、終了したすべてのアクションをチェックし(endtime <= unixtime())、それらを完了します(関連するプレーヤーに報酬を与えるなど)。
最近、完了すべきアクションが100個あり、cronjobタスク1が1分で終了しなかったため、cronjobタスク2が実行され、すべてのアクションが2回完了しました。
これが再び発生するのを防ぐにはどうすればよいですか?セッションに特定のトランザクション分離コードを使用し、更新用に行を予約する必要がありますか?
PHP5.3.18mysqlは5.5.27ですテーブルエンジンはINNODBです
毎分呼び出される現在のコードは次のとおりです。
public function complete_expired_actions ( $charflag = false )
{
// Verifying if there are actions to complete...
$db = Database::instance();
$db -> query("set autocommit = 0");
$db -> query("begin");
$sql = "select * from
character_actions
where status = 'running'
and endtime <= unix_timestamp()";
$result = $db -> query ( $sql ) ;
// try-catch. Se si verifica un errore, l' azione che commette l' errore viene rollbackata
foreach ( $result as $row )
{
try
{
$o = $this->factory( $row -> action );
$o -> complete_action ( $row );
if ($row -> cycle_flag == FALSE)
{
// non aperta ad attacchi SQl-injection perchè i parametri non sono passati via request
if ( $charflag == true )
kohana::log( 'info', "-> Completing action: " . $row -> id . ' - ' . $row -> action . " for char: " . $row->character_id );
$db->query( "update character_actions set status = 'completed' where id = " . $row->id );
// in ogni caso invalida la sessione!
Cache_Model::invalidate( $row -> character_id );
}
$db->query('commit');
} catch (Kohana_Database_Exception $e)
{
kohana::log('error', kohana::debug( $e->getMessage() ));
kohana::log('error', 'An error occurred, rollbacking action:' . $row->action . '-' . $row->character_id );
$db->query("rollback");
}
}
$db->query("set autocommit = 1");