我的MySQL数据库有180k行...其中7k是重复的。数据是通过执行POST的javascript网络应用运行的PHP(5.6.30)脚本创建的。
也就是说,它们具有相同的数据和相同的时间戳。
以下是运行以创建行的代码:
$log->lwrite('Do NOT have extCommentID / author: ' . $authorID);
$query = "INSERT INTO anno_feedback (anno_fb_author_id, anno_fb_recip_ext_id, anno_fb_recip_ext_name, anno_fb_recip_avatar_url, anno_fb_ext_id, anno_fb_ext_sys_id, anno_fb_lib_id, anno_fb_group_id, anno_fb_comment_id, anno_fb_app_source, anno_fb_platform, anno_fb_use_custom, anno_fb_comment_text, anno_fb_url_target, anno_fb_word_target) VALUES ($authorID, '". $recipientID ."', '" .$recipientName . "', '" .$recipientAvatarURL . "', '" . $extCommentID . "', $sysID, $libID, $groupID, $commentID, '" . $appSource . "', '" . $platform . "',$commentUseCustom,'" . $commentText . "','" . $urlTarget ."','" . $wordTarget ."')";
// $newFbID = mysqli_insert_id($connection); // Get ID of newly created row...
// // echo "\n\nRunning query to create Group - $query";
// $log->lwrite('New commentID created: ' . $newFbID);
} // END else for no existing feedback
// NOW, regardless, run query...
if(mysqli_query($connection, $query)){
$newFbID = mysqli_insert_id($connection); // Get ID of newly created row...
$log->lwrite('New commentID created: ' . $newFbID);
echo "\n\nCreated/updated feedback row...for row: " . $newFbID;
} else {
echo "ERROR: Was not able to execute $query. " . mysqli_error($connection);
}
还有一个日志示例:
[16 / Oct / 2018:07:13:27](saveFeedback)-------------开始为用户/ commentID保存反馈:5222/23093 [16 / Oct / 2018:07:13:27](saveFeedback)没有extCommentID /作者:5222 [16 / Oct / 2018:07:13:27](saveFeedback)创建了新的commentID:177444 [16 / Oct / 2018:07:13:27](saveFeedback)-------------开始为用户/ commentID保存反馈:5222/23093 [16 / Oct / 2018:07:13:27](saveFeedback)没有extCommentID /作者:5222 [16 / Oct / 2018:07:13:27](saveFeedback)创建了新的commentID:177445
这些行(177444和177445)是重复的。
我不认为通过POST命令运行PHP的Web应用程序存在问题(不是重复的侦听器或表单提交)。我认为PHP有时会运行两次-可能是并发性还是服务器负载问题?
PHP / MySQL解决方案可以使用哪些策略来避免这种情况?我已经读过有关INSERT IGNORE的信息,但是我必须对照文本字段和日期字段进行检查,以了解是否正在创建重复项-感觉很昂贵。
任何方向都值得赞赏-我可能不知道有一些最佳实践可以确保创建单行。很高兴提供更多细节。
答案 0 :(得分:2)
PHP / MySQL解决方案可以使用哪些策略来避免这种情况?我已经读过关于INSERT IGNORE的信息,但是我必须对照文本字段和日期字段进行检查,以了解是否正在创建重复项-感觉很昂贵
创建唯一索引。通常,您不能使“文本”字段唯一(如果您是指文本类型,而不是VarChar)。这通常是绊倒人们的绊脚石。如果需要检查“文本”字段是否唯一,那么如何获得唯一索引。
一种方法是,您可以创建数据的哈希,然后使其唯一,这几乎是一样的。您只需要维护哈希即可。例如,如果他们编辑帖子,则必须更新哈希,但实际上没什么大不了的。
例如:
$hash = hash('sha1', $date.$text);
然后在数据库中创建一个新字段,该字段是具有CHAR(40)
归类的唯一索引UTF8_bin
。 SHA1的长度为40个字节,因此UTF8_bin
是二进制格式,使搜索区分大小写。哈希是区分大小写的。
实际上,这会占用大量的文本(和日期),并将其压缩为40个字符的哈希,您可以对该索引进行唯一索引。这样就不可能有重复。 SHA1哈希非常快,我曾经对其计时,在我的PC上每秒大约有30,000个哈希。虽然我确实忘记了,所以我可能还有一段路要走,但还有很多,我需要担心何时计时。
INSERT IGNORE
这经常被误解,它所做的只是忽略错误。如果没有适当的唯一索引,则不会有重复的错误,也完全不会帮助您。它没有普通插入慢,但是除了唯一索引失败之外,它还可以抑制其他错误。
另一件事是,必须先删除重复项,然后才能修复表。您还必须返回并为已保存的那些记录创建哈希。这应该不太困难,只需确保在进行任何更改之前备份表即可。
我不认为通过POST命令运行PHP的Web应用程序存在问题(不是重复的侦听器或表单提交)。我认为PHP有时会运行两次-可能是并发性还是服务器负载问题?
就像有人双击提交按钮一样简单。我曾经有一个办公室工作人员的鼠标不好,每当她单击提交按钮时,都会双击它。由于并发,您不能仅依靠代码检查来保持其唯一性。
在数据库中有一个唯一字段,您可以使用INSRT IGNORE
,INSERT ON DUPLICATE UPDATE
或REPLACE INTO
,所有这些都避免了将其实际应用到应用程序中的错误,并且无需插入重复。所有人都有自己的小习惯。例如,INSERT ON DUPLICATE
即使在更新时也将增加自动增量ID计数器(而不是行的ID),虽然没什么大不了,但很高兴知道。 “替换”会删除当前行并插入新行,因此如果查询中未包含该行,则“自动增量ID”将发生更改。
希望有帮助!
答案 1 :(得分:0)
根据您的代码,并在日志报告中,看起来数据已两次提交到数据库。
为了克服这个问题,请在插入数据之前检查数据库表中是否存在相同的日期。那么您将不会遇到这个问题。
为此,请在插入之前添加查询以检查数据。