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

问题描述 投票:4回答:6

我正在使用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是一个索引键

我怎样才能找到问题的根源?

magento pdo duplicates constraints zend-db
6个回答
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,如果是,则不会插入它。它解决了这个问题..

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


3
投票

附加解决方案: -

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

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

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

正如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 Patch Index URL扩展将URL索引限制为仅为可单独创建的已启用产品创建记录。这非常有效。

我希望这会有所帮助!


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 - 您可能还希望将$_logAllQueries$_logCallStack更改为true)。看看$_debugFile找到tail的路径。


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运行以下查询来查找问题记录(注意查询如何与Exception相关),它发现这与已重命名的类别有关...

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;

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

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

现在,目录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重写索引已成功重建

我已经记录了我的发现,你的情况可能有所不同,但这有点解释你如何找到问题并解决它。


0
投票

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


0
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.