重建索引Magento时出现约束违规/重复键

时间:2012-08-02 15:54:47

标签: magento pdo duplicates constraints zend-db

我使用的是Magento CE 1.6.2,我的reindexer(url_rewrite)有问题

php shell/indexer.php --reindex catalog_url
Catalog URL Rewrites index process unknown error:
exception 'PDOException' with message 'SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '33432700_1343855802-0-1' for key 'UNQ_CORE_URL_REWRITE_ID_PATH_IS_SYSTEM_STORE_ID'' in /home/website/public_html/lib/Zend/Db/Statement/Pdo.php:228

当我截断core_url_rewrite ...并且第一次通过后端命中索引器时,一切都很好,我的url重写存储在core_url_rewrites中...... 但是如果我第二次启动索引器(没有刷新表),我会收到重复键的错误。

以下是我的表格的屏幕截图:https://www.dropbox.com/s/6v9uawp5v437w3h/seo_Magewroks.png

注意:UNQ_CORE_URL_REWRITE_ID_PATH_IS_SYSTEM_STORE_ID是索引键

如何找到问题的根源?

6 个答案:

答案 0 :(得分:5)

这应解决问题,

复制核心文件:/app/code/core/Mage/Catalog/Model/Resource/Url.php 收件人:/app/code/local/Mage/Catalog/Model/Resource/Url.php

找到这个功能:

public function saveRewriteHistory($rewriteData)
{
    $rewriteData = new Varien_Object($rewriteData);
    // check if rewrite exists with save request_path
    $rewrite = $this->getRewriteByRequestPath($rewriteData->getRequestPath(), $rewriteData->getStoreId());

    if ($rewrite === false) {
        // create permanent redirect
        $this->_getWriteAdapter()->insert($this->getMainTable(), $rewriteData->getData());
    }

    return $this;

}

将其替换为:

protected $_processedRewrites = array();   // add this to your class vars on top

public function saveRewriteHistory($rewriteData)
{
    $rewriteData = new Varien_Object($rewriteData);
    // check if rewrite exists with save request_path
    $rewrite = $this->getRewriteByRequestPath($rewriteData->getRequestPath(), $rewriteData->getStoreId());
    $data = $rewriteData->getData();

    $current = $data["id_path"]."_".$data["is_system"]."_".$data["store_id"];
    if ($rewrite === false && !in_array($current, $this->_processedRewrites)) {
        $this->_processedRewrites[] = $current;
        // create permanent redirect
        $this->_getWriteAdapter()->insert($this->getMainTable(), $rewriteData->getData());
    }

    return $this;
}

问题是因为函数检查数据库是为了在插入之前查看core_url_rewrites中是否存在重写。这很好。但它使用以下属性进行检查: request_path,is_system,store_id

我们的问题是有些行有重复的id_path但是有不同的request_path ...这很奇怪,不知道为什么它不应该......

但是使用这个替换函数,它还会检查之前是否处理过id_path,如果是,则不会插入它。它解决了这个问题..

但是,我们仍然不知道问题的根源

答案 1 :(得分:3)

其他解决方案: -

截断 core_url_rewrite 表时,您将丢失所有旧的URL密钥更改传播记录。我发现删除所有标记为" is_system " 1将维护这些遗留URL重定向,使用查询: -

DELETE FROM `core_url_rewrite` WHERE `is_system` = 1;

这与截断表同时保持网址更改传播或您可能创建的定制重定向具有相同的影响。

正如Alan Storm所说: -

  

is_system 属性可能更准确地命名为 is_canonical_rewrite_for_category_or_product_category_combo 。也就是说, is_system ,是一个布尔标志,Magento设置为让自己知道哪些行是系统级重写,由Magento创建,并且当前代表特定实体的“主”URL(相对于重定向重写,也由系统创建,但将 is_system 标志设置为false)。艾伦风暴 - http://alanstorm.com/

此外,如果您可以将损坏缩小到产品或类别记录,则可以使用以下内容: -

维护类别重定向: -

DELETE FROM `core_url_rewrite` WHERE `is_system` = 1 AND `category_id` IS NOT NULL;

维护产品重定向: -

DELETE FROM `core_url_rewrite` WHERE `is_system` = 1 AND `product_id` IS NOT NULL;

总体上请记住,标记为 is_system 1的所有记录都是由Magento从产品或类别数据创建的,并且可以重新创建。标记为 is_system 0的记录在其他任何地方都不存在,并且将永远丢失"死亡结束"如果你只是截断core_url_rewrite,那么来自其他网站的遗留链接。

另一个影响的问题是Magneto在重新编制索引时尝试创建的URL重定向数量。如果您有大量使用以下扩展名的产品,可以加快索引时间并减少core_url_rewrite表中的记录数量: - http://www.magentocommerce.com/magento-connect/dn-d-patch-index-url-1.html

Dn&#D; D补丁索引URL扩展将URL索引限制为仅为可单独创建的已启用产品创建记录。这非常有效。

我希望这会有所帮助!

答案 2 :(得分:2)

第一次工作,但后续的重新索引失败似乎有点不寻常。你确定你使用的是InnoDB,你的MySQL设置是否正确?我会检查以确保你的innodb缓存足够大,看看MySQL本身是否正在吐出任何类型的错误。 Magento利用了InnoDB的事务查询,如果MySQL内存或空间不足以存储来自此类大型事务的准备好的查询,则可能会遇到问题。

您获得的错误具有误导性,因为首次构建表时,第一个重新索引会捕获重复的键。如果这是一个简单的数据问题,例如重复的SKU或不正确的类别层次结构,那么索引将在第一次尝试时失败。

您可能还希望确保应用程序的MySQL用户具有足够的权限以在必要时刷新表。 Magento想要破桌子;如果不能,它可能会尝试重建,导致重复的密钥错误。

我还会尝试tail您的exception.log文件,看看是否可以获得堆栈跟踪并在此处发布。另外,尝试启用MySQL库的调试日志记录(您可以在$_debug的第103行将true的默认值更改为/lib/Varien/Db/Adapter/Pdo/Mysql.php - 您可能还希望更改{{1 }和$_logAllQueries也是如此)。查看$_logCallStack以查找$_debugFile的路径。

答案 3 :(得分:1)

我发现db用户拥有正确的权限,我不喜欢更改核心代码,无论它是否被移动到本地。

在从1.4升级到1.6之后,命令行reindex之后出现错误。

php indexer.php -reindex catalog_url
An error occurred while saving the URL rewrite

在日志中与以下异常配对: -

exception 'PDOException' with message 'SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'category/360-1-6' for key 'UNQ_CORE_URL_REWRITE_ID_PATH_IS_SYSTEM_STORE_ID'' in httpdocs/lib/Zend/Db/Statement/Pdo.php:228

我通过mysql运行以下查询来查找问题记录(注意查询与异常的关系),发现这与已重命名的类别有关...

QUERY: select * from core_url_rewrite where id_path =  "category/360";

我注意到这是一个类别url重写,并且product_id记录为0而不是NULL,我怀疑这是问题,如果你遇到这个问题,看看这对你是否相同会很有趣,运行以下内容:

QUERY: select * from core_url_rewrite where product_id=0;

当我运行上述查询时,它返回了一条记录问题记录。

我找到的解决方案是删除问题记录......

现在,catalog_url reindex可以解决问题。

运行以下查询将返回product_id为NULL的新记录,并表示新的URI路径。旧URI导致404,而不是重定向。

QUERY: select * from core_url_rewrite where id_path =  "category/360";

我认为这个问题是单个数据记录问题,可能是在升级之后。我不同意更改URL.php或截断core_url_rewrite是正确的。

我已经重建了catalog_url的索引两次,并且作为完整reindex的一部分重建了三分之一。全部返回:目录URL重写索引已成功重建

我已经记录了我的调查结果,您的情况可能有所不同,但这可以解释您如何找到问题并解决问题。

答案 4 :(得分:0)

不知道是什么原因造成了我们的网站,但修复很简单。如果您不关心旧的URL重新网站(例如,您的产品网址一直是他们现在的状态,或者您不想丢失历史记录)截断core_url_rewrite表,然后重新索引。

答案 5 :(得分:0)

最简单的解决方案是从core_url_rewrite表中删除这些记录并重新重新索引