INSERT ON DUPLICATE KEY UPDATE导致大量增量差距 - InnoDB MySQL

时间:2014-08-07 00:44:02

标签: php mysql sql

我试图在keyword表格中插入关键字,并通过articles表格将其映射到articleKeywordIndex,但是已经卡在了车辙中,并且可能会在'出去。这是我的设置:

articles
-------------
articleID    INT AUTO PRI

articleKeywordIndex
-------------
articleID    INT UNIQUE
keywordID    INT UNIQUE

keywords
-------------
keywordID    INT PRI
keyword      VARCHAR UNIQUE

使用INSERT INTO keywords (a) VALUES (:a) ON DUPLICATE KEY UPDATE a = a但是我注意到自动增量奇怪地被更新并且让我感到困惑,因为我认为这是不会发生的方法。无论如何,我还需要抓住keywordID是否存在,放入调音台,所以我去了一个try / catch解决方案,如果INSERT由于一个唯一的条目而失败,那么会选择要在另一个表中使用的keywordID。

现在发生了什么,如果关键字尚未存在,并且该表中已有4个关键字(1,2,3,4),则关键字表中的keywordID列会增加4 ,插入时将其设为8。如果这种情况一直发生并且我有很多关键字,那么关键字ID列的ID将是huuuuge!如果关键字DOES存在,则没有任何改变并且完美地运行。我想象它与循环循环4次有关,但我看不出问题。

以下是代码:

$tagsArray = explode(',', strtolower($tags));
for ($x = 0; $x < count($tagsArray); $x++) {

    $keyword = trim($tagsArray[$x]);

    try {
        $SQL = "INSERT INTO keywords (keyword) VALUES (:keyword);";
        $STH = $DBH -> prepare($SQL);
        $STH -> bindParam(':keyword', $keyword);
        $STH -> execute();
        $keywordID = $DBH -> lastInsertId();
    } catch (Exception $e) {
        $SQL = "SELECT keywordID FROM keywords WHERE keyword = :keyword;";
        $STH = $DBH -> prepare($SQL);
        $STH -> bindParam(':keyword', $keyword);
        $STH -> execute();
        $keywordID = $STH -> fetchColumn();
    }

    $SQL = "INSERT INTO articleKeywordIndex (articleID, keywordID) VALUES (:saveToID, :keywordID)
        ON DUPLICATE KEY UPDATE articleID = articleID, keywordID = keywordID;";
    $STH = $DBH -> prepare($SQL);
    $STH -> bindParam(':saveToID', $saveToID);
    $STH -> bindParam(':keywordID', $keywordID);
    $STH -> execute();

}

我认为这不是很多,因为我只有~3000-5000个关键词,但它仍然很烦人,想知道出了什么问题。

解决方案

事实证明,使用INSERT ON DUPLICATE KEY UPDATE时,使用InnoDB引擎会导致奇数增量更改。这实际上是几年前报告的一个错误并且发布了补丁,但后来它被证明是一个特意设计的功能,my.cnf中的设置禁用它。这是一个奇怪的故事,需要一段时间来了解它。无论如何,在my.cnf,我改变了这个:

innodb_autoinc_lock_mode=0

所有这些都恢复正常,我的脚本按照我的想法,当我第一次写它时,在其他五次尝试之前!我使用InnoDB进行交易,因此我还没有准备好切换到MyISAM。

2 个答案:

答案 0 :(得分:1)

您的代码看起来不错?我可能会尝试以下操作,看看是否有效。

  • 首先,使用SELECT @@auto_increment_increment;检查auto_increment_increment。也许出于某种原因它被设置为4?

  • 如果您手动使用mySQL添加记录怎么办?它还能上升到4吗?如果是,则可能与您的代码无关。

  • 你说它可能与循环循环4次有关。您是否尝试使用化妆阵列进行循环,例如... 6个元素?它会上升到6?

  • 我还要检查并确保没有任何隐藏的程序或触发器在幕后工作。

EDIT1:准备离开循环。我认为既然有或没有on update你似乎仍然有奇数增量值问题,也可以再次使用...on update

$tagsArray = explode(',', strtolower($tags));
$SQL = "INSERT INTO keywords (keywordID, keyword) VALUES (NULL, :keyword) 
            ON DUPLICATE KEY UPDATE keywordID=LAST_INSERT_ID(keywordID), keyword = keyword;
        INSERT INTO articleKeywordIndex (articleID, keywordID) VALUES (:saveToID, LAST_INSERT_ID())
            ON DUPLICATE KEY UPDATE articleID = articleID, keywordID = keywordID;";
$STH = $DBH -> prepare($SQL);
$STH -> bindParam(':saveToID', $saveToID);   //<--I actually haven't tried this, if it doesn't work move it back into loop.

for ($x = 0; $x < count($tagsArray); $x++) {
        $STH -> bindParam(':keyword', trim($tagsArray[$x]));
        $STH -> execute();
}

答案 1 :(得分:0)

事实证明,当使用INSERT ON DUPLICATE KEY UPDATE时,使用InnoDB引擎会导致奇数增量更改。这实际上是几年前报告的一个错误并且发布了补丁,但后来它被证明是一个特意设计的功能,my.cnf中的设置禁用它。这是一个奇怪的故事,需要一段时间来了解它。无论如何,在my.cnf,我改变了这个:

innodb_autoinc_lock_mode = 0

一切都恢复正常。我使用InnoDB进行交易,因此我还没有准备好切换到MyISAM。