2013-04-09 92 views
0

我似乎在插入一行兩次MySQL有一些困難。 - 基本上,我需要保存從遠程數據源檢索到的一些信息的本地副本。因此,當用戶查看來自遠程源的信息時,我會檢查是否有我需要存儲的信息的本地副本。如果我沒有本地副本,請添加該信息的記錄。 - 我遇到的問題是每個我會說20-30插入我得到一個副本。我使用NOW函數跟蹤插入和更新時間,並且兩個記錄似乎都是同時插入的。 這裏是我的PHP代碼,任何幫助將是非常讚賞,我很爲難:MySQL行插入兩次

// We have the location, see if we have a local record for that location 
     $idLocation = locationID_for_factualID($factual_id); 
     if(!$idLocation) { 
      // We do not have local information about the location, add it 
      $mysqli = open_mysql_connection(); 
      $stmt = $mysqli->prepare("INSERT INTO Location (
                factual_id, 
                dateAdded, 
                dateModified, 
                locationName, 
                latitude, 
                longitude) 
               VALUES (?, NOW(), NOW(), ?, ?, ?)"); 
      if($stmt) { 
       $stmt->bind_param("ssdd",$factual_id, $location["name"], doubleval($location["latitude"]), doubleval($location["longitude"])); 
       $stmt->execute(); 
       // Check if the location was added 
       if($stmt->affected_rows == 1){ 
        $idLocation = locationID_for_factualID($factual_id); 
       } 
       $stmt->close(); 
       $mysqli->close(); 
      } 
      else { 
       return FALSE; 
      } 
     } 

下面是兩行,似乎是插入背靠背:

idLocation | factual_id | dateAdded | dateModified | locationName | latitude | longitude 
520 | 5f79360f-330f-4035-ae75-e872ea14cfdd | 2013-04-09 14:36:55 | 2013-04-09 14:36:55 | Quiznos | 40.1802 | -74.0258 
521 | 5f79360f-330f-4035-ae75-e872ea14cfdd | 2013-04-09 14:36:55 | 2013-04-09 14:36:55 | Quiznos | 40.1802 | -74.0258 
+0

'locationID_for_factualID'在做什麼? – 2013-04-09 14:55:25

+0

如果找到包含事實ID的行,則locationID_for_factualID返回Location.idLocation,否則返回FALSE。所以基本上,如果該行存在,它會返回該位置的本地ID,否則返回FALSE。 – dbrateris 2013-04-09 15:00:48

回答

0

雖然我不看到你的實現locationID_for_factualID,我很確定它正在做類似SELECT idLocation ... WHERE factual_id = '$factual_id'(不要忘記使用查詢參數!)。

我可以想象你有一個競爭條件,即兩個請求在幾乎同一時間用相同的輸入數據調用相同的腳本,然後調用函數locationID_for_factualID,並且都發現$idLocation == false。然後,這兩個請求都會執行INSERT,最後會出現重複記錄。

此問題的標準解決方案是使用事務。看看here這是怎麼完成的。重要的部分是用locationID_for_factualIDINSERT包裝SELECT,具有相同的交易,即在START TRANSACTIONCOMMIT之間。您可能必須更改locationID_for_factualID的實施以使用與以下INSERT相同的數據庫連接。

另外,您可能想要在列factual_id上創建一個UNIQUE INDEX。如果嘗試插入重複,則會使INSERT語句失敗,從而防止相同的factual_id發生多次。

+0

謝謝,我可以做出這些改變,並立即調查。 但是,我確信這不是一個競爭條件,因爲我只是測試了這一點,而且我是唯一的用戶。我想有可能我使用的設備提出了兩個請求,但我非常懷疑它。 – dbrateris 2013-04-09 15:17:08