我对MySQL似乎插入两次行有些困难。-基本上,我需要保存从远程数据源检索到的某些信息的本地副本。因此,当用户查看来自远程源的信息时,我会检查是否有需要存储的信息的本地副本。如果我没有本地副本,我会添加该信息的记录。-我遇到的问题是,每插入20-30个插件,我就会得到一个副本。我使用NOW函数跟踪插入和更新时间,这两条记录似乎是同时插入的。这是我的PHP代码,任何帮助都会非常感谢,我被难住了:
// 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发布于 2013-04-09 23:08:11
尽管我没有看到您的locationID_for_factualID实现,但我非常确定它正在做类似于SELECT idLocation ... WHERE factual_id = '$factual_id'的事情(不要忘记使用查询参数!)。
我可以想象你有一个竞争条件,即两个请求几乎在同一时间使用相同的输入数据调用相同的脚本,然后调用函数locationID_for_factualID并都找到那个$idLocation == false。然后,两个请求都执行INSERT,最后得到一个重复的记录。
这个问题的标准解决方案是使用事务。看看here是如何做到这一点的。重要的部分是用相同的事务包装locationID_for_factualID和INSERT内部的SELECT,即在START TRANSACTION和COMMIT之间。您可能必须更改locationID_for_factualID的实现,以使用与以下INSERT相同的DB连接。
另外,您可能希望在列factual_id上创建一个UNIQUE INDEX。这将通过让INSERT语句在尝试插入重复项时失败来防止相同的factual_id多次出现。
https://stackoverflow.com/questions/15905188
复制相似问题