我正在尝试将关键字插入到 keyword
表中,并通过 articleKeywordIndex
表将它们映射到 articles
,但卡住了车辙,不能出去。这是我的设置:
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 由于唯一条目而失败, catch 将选择该 keywordID 以在另一个表中使用。
现在发生的事情是,如果关键字不存在,并且该表中已经有 4 个关键字 (1,2,3,4),则关键字表中的 keywordID 列递增 4,使其变为 8当它被插入时。如果这种情况持续发生并且我有很多关键字,则 keywordID 列的 ID 将是 huuuuge!如果关键字确实存在,则不会发生任何变化并且可以完美运行。我想这与循环循环 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。
最佳答案
你的代码看起来没问题?我可能会尝试以下操作,看看是否有任何效果。
首先,使用
SELECT @@auto_increment_increment;
检查 auto_increment_increment。也许由于某种原因它被设置为 4?如果您使用 mySQL 手动添加记录怎么办?还会涨4吗?如果是,那么可能与您的代码无关。
你说可能和loop循环4次有关。您是否尝试过使用化妆阵列来制作带有 say...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();
}
关于php - INSERT ON DUPLICATE KEY UPDATE 导致较大的增量差距 - InnoDB MySQL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25172543/