为什么我的PHP代码有时会在MySQL数据库中创建多行?

时间:2018-10-17 17:29:59

标签: php mysql mysqli

我的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的信息,但是我必须对照文本字段和日期字段进行检查,以了解是否正在创建重复项-感觉很昂贵。

任何方向都值得赞赏-我可能不知道有一些最佳实践可以确保创建单行。很高兴提供更多细节。

2 个答案:

答案 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 IGNOREINSERT ON DUPLICATE UPDATEREPLACE INTO,所有这些都避免了将其实际应用到应用程序中的错误,并且无需插入重复。所有人都有自己的小习惯。例如,INSERT ON DUPLICATE即使在更新时也将增加自动增量ID计数器(而不是行的ID),虽然没什么大不了,但很高兴知道。 “替换”会删除当前行并插入新行,因此如果查询中未包含该行,则“自动增量ID”将发生更改。

希望有帮助!

答案 1 :(得分:0)

根据您的代码,并在日志报告中,看起来数据已两次提交到数据库。

为了克服这个问题,请在插入数据之前检查数据库表中是否存在相同的日期。那么您将不会遇到这个问题。

为此,请在插入之前添加查询以检查数据。