2013-04-09 5 views
0

MySQL에서 행을 두 번 삽입하는 데 어려움이 있습니다. - 기본적으로 원격 데이터 원본에서 검색되는 일부 정보의 로컬 복사본을 저장해야합니다. 따라서 사용자가 원격 소스의 정보를 볼 때 저장해야하는 정보의 로컬 사본이 있는지 확인합니다. 로컬 사본이 없으면 해당 정보의 레코드를 추가합니다. - 내가 가지고있는 문제는 내가 20-30 개의 삽입물을 넣을 때마다 복제물을 얻는다는 것입니다. NOW 함수를 사용하여 삽입 및 업데이트 시간을 추적하며 두 레코드가 동시에 삽입 된 것처럼 보입니다. 여기 내 PHP 코드는 어떤 도움은 매우 내가 난처한 상황에 빠진하고, 평가 될 것입니다 :MySQL 행이 두 번 삽입되었습니다.

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'는 무엇을하고 있습니까? –

+0

locationID_for_factualID는 사실 ID가있는 행을 찾으면 Location.idLocation을 리턴하고, 그렇지 않으면 FALSE를 리턴합니다. 그래서 기본적으로 행이 존재하면 그 위치에 대한 내 로컬 ID를 반환하고, 그렇지 않으면 FALSE를 반환합니다. – dbrateris

답변

0

을 내가하지 않지만 :

// 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; 
      } 
     } 

여기 다시 다시 삽입하는 것 두 행은 locationID_for_factualID 구현을 참조하십시오, 나는 꽤 SELECT idLocation ... WHERE factual_id = '$factual_id' (쿼리 매개 변수를 사용하는 것을 잊지 마세요!) 같은 것을하고 있는지 확인합니다.

경쟁 조건이 있다고 상상해보십시오. 즉, 거의 동일한 시간에 동일한 입력 데이터로 동일한 스크립트를 호출 한 다음 두 가지 요청을 수행하면 locationID_for_factualID 함수를 호출하고 그 둘 모두는 $idLocation == false입니다. 그런 다음 두 요청 모두 INSERT을 실행하고 중복 기록으로 끝납니다.

이 문제의 표준 해결책은 트랜잭션을 사용하는 것입니다. 이 방법은 here입니다. 중요한 부분은 SELECTlocationID_for_factualID 안에 넣고 INSERT을 동일한 거래 (예 : START TRANSACTIONCOMMIT)로 묶는 것입니다. INSERT과 동일한 DB 연결을 사용하려면 locationID_for_factualID 구현을 변경해야 할 것입니다.

이외에도 factual_id 열에 UNIQUE INDEX을 생성 할 수 있습니다. 중복을 삽입하려고하면 INSERT 문이 실패하도록하여 동일한 factual_id가 두 번 이상 나타나지 않도록합니다.

+0

감사합니다. 이러한 변경을 수행 할 수 있으며 즉시이를 조사 할 것입니다. 그러나 나는 이것이 단지 테스트를 거쳤고 나는 유일한 사용자 였기 때문에 이것이 경쟁 조건이 아니라고 확신합니다. 나는 내가 사용하고있는 장치가 두 가지 요청을했을 가능성이 있다고 생각하지만, 나는 그것을 의심하고있다. – dbrateris

관련 문제