을 내가하지 않지만 :
// 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입니다. 중요한 부분은 SELECT
을 locationID_for_factualID
안에 넣고 INSERT
을 동일한 거래 (예 : START TRANSACTION
및 COMMIT
)로 묶는 것입니다. INSERT
과 동일한 DB 연결을 사용하려면 locationID_for_factualID
구현을 변경해야 할 것입니다.
이외에도 factual_id 열에 UNIQUE INDEX
을 생성 할 수 있습니다. 중복을 삽입하려고하면 INSERT
문이 실패하도록하여 동일한 factual_id가 두 번 이상 나타나지 않도록합니다.
'locationID_for_factualID'는 무엇을하고 있습니까? –
locationID_for_factualID는 사실 ID가있는 행을 찾으면 Location.idLocation을 리턴하고, 그렇지 않으면 FALSE를 리턴합니다. 그래서 기본적으로 행이 존재하면 그 위치에 대한 내 로컬 ID를 반환하고, 그렇지 않으면 FALSE를 반환합니다. – dbrateris