2012-11-25 14 views
0

我有以下代碼:代碼有時會創建重複的行?

$sth = $dbh->prepare("SELECT * FROM stats WHERE player_id = :player_id AND data_type = :data_type"); 

$sth->bindParam(':player_id', $player_id); 
$sth->bindParam(':data_type', $total_time_data_type_id); 
$sth->execute(); 

$result = $sth->fetch();    

if(!$result){ 
    $sth = $dbh->prepare("INSERT INTO stats (player_id, offset, created, modified, last_check, data_type, data) VALUES (:player_id, :offset, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), '1', :total_time_data_type_id, '0')"); 

    $sth->bindParam(':player_id', $player_id); 
    $sth->bindParam(':offset', $offset); 
    $sth->bindParam(':total_time_data_type_id', $total_time_data_type_id); 
    $sth->execute(); 

    if(!$sth){ 
     return false; 
    } 
    $sth = $dbh->prepare("SELECT * FROM stats WHERE player_id = :player_id AND data_type = :data_type"); 

    $sth->bindParam(':player_id', $player_id); 
    $sth->bindParam(':data_type', $total_time_data_type_id); 
    $sth->execute(); 

    $result = $sth->fetch(); 
    if(!$result){ 
     return false; 
    } 
}else{ 
    $sth = $dbh->prepare("UPDATE stats SET ....."); 
    //Do more stuff 
} 

現在,偶爾出現這種創造重複的行(600個出來行〜,有23個重複)。這使我困惑,因爲在插入行之前,我明確檢查了具有相同的player_iddata_type的行。

對於相同的player_iddata_type可以存在多行,但每個行都不相同。

I.E.這將是有效的:

ID | PLAYER_ID | DATA_TYPE 
---|-----------|---------- 
1 | 15  | 7 
2 | 15  | 18 
3 | 92  | 7 
4 | 115  | 23 

雖然不會:

ID | PLAYER_ID | DATA_TYPE 
---|-----------|---------- 
1 | 15  | 7   
2 | 32  | 18  
3 | 15  | 7   
4 | 115  | 23 

正因爲如此,我不能簡單地聲明player_id領域獨一無二。

我能想到的唯一可能導致這個問題的事實是,上面的代碼片段在一個平均大約115次迭代的foreach循環中,並且這個代碼在幾秒鐘內再次被調用。有沒有一種方法來防止這種編程方式?

+0

當你有兩個同時運行的代碼副本時會發生什麼?第一個可以進行檢查並發現需要添加一個球員;如果第二個副本在該點之後但在添加該玩家之前運行,則會得到重複的條目。 – andrewsi

+0

@andrewsi這就是我所設想的,但有沒有一種方法來防止這種方式? –

+1

只需使用「INSERT ... ON DUPLICATE KEY UPDATE」 – nikita2206

回答

0

感謝大家的幫助,特別是@ nikita2206。這是我解決我的問題的方法:

  1. 刪除的列ID是主鍵。
  2. 在(Player_id,data_type)上創建新的主鍵。
  3. 更改的INSERT語句:

$sth = $dbh->prepare("INSERT INTO stats (player_id, offset, created, modified, last_check, data_type, data) VALUES (:player_id, :offset, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), '1', :total_time_data_type_id, '0')"); 

$sth = $dbh->prepare("INSERT INTO stats (player_id, offset, created, modified, last_check, data_type, data) VALUES (:player_id, :offset, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), '1', :total_time_data_type_id, '0') ON DUPLICATE KEY UPDATE player_id = player_id"); 

測試通過調用代碼幾次非常迅速,沒有創建副本。