【问题标题】:How does Magento manage foreign key constraintMagento 如何管理外键约束
【发布时间】:2014-03-23 12:22:05
【问题描述】:

我最近升级到法师 1.8.1。似乎一切都很好,但重新索引产品价格。发现以下错误:

#1452 - Cannot add or update a child row: a foreign key constraint fails (`threeleavednew`.`catalog_product_index_tier_price`, CONSTRAINT `FK_CAT_PRD_IDX_TIER_PRICE_ENTT_ID_CAT_PRD_ENTT_ENTT_ID` FOREIGN KEY (`entity_id`) REFERENCES `catalog_product_entity` (`entity_id)

此数据库在升级之前由 phpMyadmin 导出并导入到新的空数据库(在我的域托管下创建)。我刚刚提取了 mage 1.8.1.tar.gz 并复制了我的主题并通过修改 local.xml 将 Mage 1.8 指向新数据库(保持加密密钥不变),将 mage 1.8 目录重命名为 httpdocs 并启动我的网站....

  1. 我不确定这种升级方式是否会导致任何数据库外键问题。
  2. 我的旧网站是从其他开发人员那里转移过来的,我不确定数据库从第一天起是否存在 FK 问题,可能与 1.8 版不兼容。

我所做的是

1) 在 phpMyadmin 中使用以下语句

select *
from INFORMATION_SCHEMA.TABLE_CONSTRAINTS
where CONSTRAINT_TYPE = 'FOREIGN KEY';

转储旧数据库、当前数据库和 Mage 示例数据库中的所有外键。比较一下。

2) 在 phpMyadmin 中运行 export 以转储当前 DB 和 Mage 示例 DB,与升级前导出的旧 DB 进行比较。

这是结果。

1) 在 Mage 示例 DB 外键表中,我可以找到以下 catalog_product_index_tier_price 表的三个 FK 键

'FK_CAT_PRD_IDX_TIER_PRICE_CSTR_GROUP_ID_CSTR_GROUP_CSTR_GROUP_ID',
'FK_CAT_PRD_IDX_TIER_PRICE_ENTT_ID_CAT_PRD_ENTT_ENTT_ID', 
'FK_CAT_PRD_IDX_TIER_PRICE_WS_ID_CORE_WS_WS_ID', 

catalog_product_flat_1、_2、_3 表各有一个 FK。

'FK_CAT_PRD_FLAT_1_ENTT_ID_CAT_PRD_ENTT_ENTT_ID',
'FK_CAT_PRD_FLAT_2_ENTT_ID_CAT_PRD_ENTT_ENTT_ID', 
'FK_CAT_PRD_FLAT_3_ENTT_ID_CAT_PRD_ENTT_ENTT_ID',

但是,当我尝试在不同时间从旧数据库和当前数据库转储 FK 表时,我有时可以找到 catalog_product_index_tier_price 表的三个 FK,有时我根本找不到它们,有时找到 FK 名称,如'FK_6E08D719F0501DD1D8E6D4EFF2511C85'。而且我从来没有为 catalog_product_flat_1、_2、_3 表找到任何 FK。

2) 在旧数据库和当前数据库导出的 .sql 文件中,我没有找到任何如下语句来为表 catalog_product_index_tier_price 和 catalog_product_flat_1, _2, _3 添加 FK,但我在从 Mage 导出的 .sql 文件中找到了它们示例数据库。

ALTER TABLE `catalog_product_index_tier_price`
ADD CONSTRAINT `FK_CAT_PRD_IDX_TIER_PRICE_CSTR_GROUP_ID_CSTR_GROUP_CSTR_GROUP_ID` FOREIGN KEY (`customer_group_id`) REFERENCES `customer_group` (`customer_group_id`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `FK_CAT_PRD_IDX_TIER_PRICE_ENTT_ID_CAT_PRD_ENTT_ENTT_ID` FOREIGN KEY (`entity_id`) REFERENCES `catalog_product_entity` (`entity_id`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `FK_CAT_PRD_IDX_TIER_PRICE_WS_ID_CORE_WS_WS_ID` FOREIGN KEY (`website_id`) REFERENCES `core_website` (`website_id`) ON DELETE CASCADE ON UPDATE CASCADE;

ALTER TABLE `catalog_product_flat_1`
ADD CONSTRAINT `FK_CAT_PRD_FLAT_1_ENTT_ID_CAT_PRD_ENTT_ENTT_ID` FOREIGN KEY (`entity_id`) REFERENCES `catalog_product_entity` (`entity_id`) ON DELETE CASCADE ON UPDATE CASCADE;

好的,看起来我的旧数据库和当前数据库都出现了 FK 问题,症状不稳定。很明显,我的所有历史数据库备份文件都没有声明为那些表添加 FK,其中一个表我用来为我遇到问题的 mage 1.8 运行导入数据库。我无法检查我的当前问题是由错误的升级方式引起的,还是从第一天开始就可能存在。

我的问题是

  1. Mage 1.8 管理数据库的方式与以前的版本不同吗?尽管我几乎不这么认为。
  2. Magento 实际上是如何管理 FK 约束的?它是在一开始就分配 FK 约束名称和关系并保持所有它们静态不变,还是随着销售或客户的变化动态分配/重新分配 FK 约束名称和关系?我的理解是 FK 约束名称和关系永远不会改变,它的数据会随着站点的运行而变化。
  3. 为什么 phpMyadmin 导出功能转储数据库备份(甚至在升级之前,当站点工作正常时)与 Mage 示例数据库上的相同转储相比,“添加约束”语句要少得多?这是否意味着我的数据库从第一天起就出现了错误/问题 FK?如果是,为什么我升级到 1.8 后才出现问题?
  4. 假设 Magento 静态管理 FK,是否有一个标准/参考 Magento FK 约束列表,我们可以将其与我们的问题进行比较以便于 DB 调试?

我真的迷路了,希望有人能帮我解决这些问题。先感谢您。 我在谷歌搜索中看到了许多与我类似的法师FK错误线程,它们都没有给我一个合理且合乎逻辑的解决方案和解释。我希望有一个解决方案,我可以看到它为什么以及如何解决问题,而不仅仅是告诉我“截断一些表,你会解决问题”....

非常感谢。

更新:我已经尝试跟踪查询流程并找到一些信息,希望高手知道问题所在。

## 17493 ## TRANSACTION BEGIN
TIME: 0.0001
## 2014-03-28 18:00:03
## 17493 ## QUERY
SQL: DELETE FROM `catalog_product_index_price_idx`
AFF: 410
TIME: 0.0055
## 2014-03-28 18:00:03
## 17493 ## QUERY
SQL: SELECT `cw`.`website_id`, `csg`.`default_store_id` AS `store_id` FROM `core_website` AS `cw`
INNER JOIN `core_store_group` AS `csg` ON cw.default_group_id = csg.group_id WHERE  (cw.website_id != 0)
AFF: 1
TIME: 0.0006
## 2014-03-28 18:00:03
## 17493 ## QUERY
SQL: DELETE FROM `catalog_product_index_website`
AFF: 1
TIME: 0.0003
## 2014-03-28 18:00:03
## 17493 ## QUERY
SQL: INSERT INTO `catalog_product_index_website` (`website_id`,`website_date`,`rate`) VALUES  (?, ?, ?)
BIND: array (  0 => '1',  1 => '2014-03-29',  2 => 1,)
AFF: 1
TIME: 0.0002
## 2014-03-28 18:00:03
## 17493 ## QUERY
SQL: DELETE FROM `catalog_product_index_tier_price`
AFF: 0
TIME: 0.0002
## 2014-03-28 18:00:03
## 17493 ## QUERY
SQL: DESCRIBE `catalog_product_index_tier_price`
AFF: 4
TIME: 0.0005

## 2014-03-28 18:00:03
## 17493 ## QUERY
SQL: INSERT INTO `catalog_product_index_tier_price` SELECT `tp`.`entity_id`, `cg`.`customer_group_id`, `cw`.`website_id`, MIN(IF(tp.website_id = 0, ROUND(tp.value * cwd.rate, 4), tp.value)) FROM `catalog_product_entity_tier_price` AS `tp`
INNER JOIN `customer_group` AS `cg` ON tp.all_groups = 1 OR (tp.all_groups = 0 AND tp.customer_group_id = cg.customer_group_id)
INNER JOIN `core_website` AS `cw` ON tp.website_id = 0 OR tp.website_id = cw.website_id
INNER JOIN `catalog_product_index_website` AS `cwd` ON cw.website_id = cwd.website_id WHERE (cw.website_id != 0) GROUP BY `tp`.`entity_id`,
`cg`.`customer_group_id`,
`cw`.`website_id` ON DUPLICATE KEY UPDATE `min_price` = VALUES(`min_price`)
TIME: 0.0069

    ## 2014-03-28 18:00:03
    EXCEPTION 
    exception 'PDOException' with message 'SQLSTATE[23000]: Integrity constraint violation: 1452  Cannot add or update a child row: a foreign key constraint fails (`threeleavednew`.`catalog_product_index_tier_price`, CONSTRAINT `FK_CAT_PRD_IDX_TIER_PRICE_ENTT_ID_CAT_PRD_ENTT_ENTT_ID` FOREIGN KEY (`entity_id`) REFERENCES `catalog_product_entity` (`entity_)' in /var/www/vhosts/3leavedcart.com/httpdocs/lib/Zend/Db/Statement/Pdo.php:228
    Stack trace:
    #0 /var/www/vhosts/3leavedcart.com/httpdocs/lib/Zend/Db/Statement/Pdo.php(228): PDOStatement->execute(Array)
    #1 /var/www/vhosts/3leavedcart.com/httpdocs/lib/Varien/Db/Statement/Pdo/Mysql.php(110): Zend_Db_Statement_Pdo->_execute(Array)
    #2 /var/www/vhosts/3leavedcart.com/httpdocs/app/code/core/Zend/Db/Statement.php(291): Varien_Db_Statement_Pdo_Mysql->_execute(Array)
    #3 /var/www/vhosts/3leavedcart.com/httpdocs/lib/Zend/Db/Adapter/Abstract.php(479): Zend_Db_Statement->execute(Array)
    #4 /var/www/vhosts/3leavedcart.com/httpdocs/lib/Zend/Db/Adapter/Pdo/Abstract.php(238): Zend_Db_Adapter_Abstract->query('INSERT INTO `ca...', Array)
    #5 /var/www/vhosts/3leavedcart.com/httpdocs/lib/Varien/Db/Adapter/Pdo/Mysql.php(428): Zend_Db_Adapter_Pdo_Abstract->query('INSERT INTO `ca...', Array)
#6 /var/www/vhosts/3leavedcart.com/httpdocs/app/code/core/Mage/Catalog/Model/Resource/Product/Indexer    /Price.php(455): Varien_Db_Adapter_Pdo_Mysql->query('INSERT INTO `ca...')
#7 /var/www/vhosts/3leavedcart.com/httpdocs/app/code/core/Mage/Catalog/Model/Resource/Product/Indexer    /Price.php(379): Mage_Catalog_Model_Resource_Product_Indexer_Price->_prepareTierPriceIndex()
    #8 /var/www/vhosts/3leavedcart.com/httpdocs/app/code/core/Mage/Index/Model/Indexer/Abstract.php(143): Mage_Catalog_Model_Resource_Product_Indexer_Price->reindexAll()
    #9 /var/www/vhosts/3leavedcart.com/httpdocs/app/code/core/Mage/Index/Model/Process.php(210): Mage_Index_Model_Indexer_Abstract->reindexAll()
    #10 /var/www/vhosts/3leavedcart.com/httpdocs/app/code/core/Mage/Catalog/Model/Observer.php(203): Mage_Index_Model_Process->reindexAll()
    #11 [internal function]: Mage_Catalog_Model_Observer->reindexProductPrices(Object(Mage_Cron_Model_Schedule))
    #12 /var/www/vhosts/3leavedcart.com/httpdocs/app/code/core/Mage/Cron/Model/Observer.php(325): call_user_func_array(Array, Array)
    #13 /var/www/vhosts/3leavedcart.com/httpdocs/app/code/core/Mage/Cron/Model/Observer.php(72): Mage_Cron_Model_Observer->_processJob(Object(Mage_Cron_Model_Schedule), Object(Mage_Core_Model_Config_Element))
    #14 /var/www/vhosts/3leavedcart.com/httpdocs/app/code/core/Mage/Core/Model/App.php(1338): Mage_Cron_Model_Observer->dispatch(Object(Varien_Event_Observer))
    #15 /var/www/vhosts/3leavedcart.com/httpdocs/app/code/core/Mage/Core/Model/App.php(1317): Mage_Core_Model_App->_callObserverMethod(Object(Mage_Cron_Model_Observer), 'dispatch', Object(Varien_Event_Observer))
    #16 /var/www/vhosts/3leavedcart.com/httpdocs/app/Mage.php(448): Mage_Core_Model_App->dispatchEvent('default', Array)
    #17 /var/www/vhosts/3leavedcart.com/httpdocs/cron.php(76): Mage::dispatchEvent('default')
    #18 {main}

以下仅在 mysqld.log 文件中查找

140319 16:41:21  InnoDB: Error: in ALTER TABLE `threeleavednew`.`catalog_product_index_tier_price`
InnoDB: has or is referenced in foreign key constraints
InnoDB: which are not compatible with the new table definition.

我还比较了我的数据库中的表 catalog_product_index_tier_price 和 Mage 示例数据库中的表结构和相关约束名称 + 关系...事实上,我比较了我怀疑的 10 多个表,没有任何线索。

谢谢。

【问题讨论】:

    标签: mysql magento upgrade


    【解决方案1】:

    我认为你有点过于复杂了。 Magento 具有在安装时设置的 FK 约束。我认为可能发生的情况是,您的 Magento 的数据库结构在此过程中被损坏了,并且最近升级到 1.8 - 表被修饰了一下,当它们被修饰时,FK 约束被重置为它们应该的样子。

    长话短说,您可能有一个错误的扩展,或者您可能想查看可能导致您的数据库结构损坏的原因。由于您刚刚升级,新结构更有可能是正确的结构。

    最后一点:价格索引的好处是,它是您可以截断表并重新应用索引而不会产生任何后果的索引之一。我建议您这样做,看看是否有帮助。

    【讨论】:

    • 感谢您的建议。我是 Magento 和 Mysql 的新手,太多的事情对我来说很神秘......如果我可以确认 Magento 静态管理所有 FK 约束并且 Mage 示例 DB 可以作为参考,那么将有一种方法可以解决任何 FK 问题,即我在找什么。我和你有同样的看法,我的数据库损坏了,index_tier_price 表可能不是唯一有问题的表,其他表的 FK 问题可能还没有出现。
    • 嗨罗恩。请您确认我升级的方式是正确的升级方式之一吗?我想确保升级本身没有注入任何潜在的数据库问题...
    • 嗨罗恩。我已经截断了表 catalog_product_index_tier_price。它没有帮助。事实上,在我截断它之前,表是空的。
    • 我不确定您是如何升级的。但是,Magento 提供了一个 DB repair 工具,您可能想研究一下。
    • 我确实想尝试一下,但它首先说要比较两个损坏的数据库与参考,然后它的逐步说明说克隆损坏的数据库 2 并创建空数据库 3,然后运行用数据库 3 修复 tools.php 让我很困惑...如果数据库 3 为空,与谁比较?
    【解决方案2】:

    时间在流逝,所以我决定采用我第一次回复 Ron 时脑海中的古老方法......花了我半天多的时间,但总比花几天时间尝试其他方法没有希望...对于那些在社区中遇到类似错误的人,我不确定这是否是最终解决方案,以防万一有人搜索此线程。

    这就是我所做的,之后,重新索引产品价格和标签将是小菜一碟。

    1. 转储你的数据库并用编辑器打开它,找到所有指向'catalog_product_entity.entity_id'的FK关系,这是父表,记下子表。其中大部分以目录或标签等开头。
    2. 打开您的 phpMyAdmin 或类似工具,使用以下语句在这些子表中查找 Fk 'entity_id' 或 'product_id' 引用 'catalog_product_entity.entity_id' 但不再存在于父表中的任何行并将它们全部删除。

      选择 * FROM child table name WHERE “product_id”或“enitty_id”不在(从“catalog_product_entity”中选择“entity_id”);

    3. 仅删除使用此语句找到的行,并将其余行保留在那里。

    您可能必须一张一张地执行此操作,有些 FK 是 'product_id',有些是 'enitty_id',所以要小心...我的数据库有一些产品之前被删除,而这些产品不在 'catalog_product_entity' 中表不再存在,但它们的旧 'entity_id' 仍然存在于与 'catalog_product_entity' 表具有约束关系的许多其他表中。我所做的是找出这些行并将它们从子表中删除。在 phpMyadmin 中删除表行非常简单。

    就是这样,去清除 var/cache 和 var/locks,登录 beckend admin 重新索引并看到所有绿色!

    这个问题的先决条件是 Magento 的所有 FK 约束(名称和关系)都定义一次并保持不变......这是我被问到的,一开始并不确定。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多