0
你好,我有一個瀏覽器遊戲,其中各種玩家安排可以持續一個或兩個小時的行動。 cronjob每分鐘檢查完成的所有動作(endtime < = unixtime())並完成它們(給予相關玩家獎勵等);PHP,MySQL和併發更新
最近發生了 - 比如說 - 100個動作要完成,而cronjob任務1在一分鐘內沒有完成,所以cronjob任務2被觸發,結果是所有完成兩次的動作。
我該如何避免這種情況再次發生?我必須爲會話使用特定的事務隔離代碼並保留行以進行更新?
PHP 5.3.18 是mysql 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");
好的,這將工作我猜,因爲下一個cronjobs將得到一個單獨的查詢集。謝謝,我會嘗試這個想法。 – Sunchaser