Skip to content

Upgrade scripts disable foreign key checks #9694

Closed
@jantzenw

Description

@jantzenw

Magento\Framework\DB\Adapter\Pdo\Mysql::startSetup is disabling foreign key checks, causing deletions in upgrade scripts to not propagate. This behavior was introduced in Magento CE 1.6 (August 2011) and should be revisited.

Preconditions

Magento CE 2.1.6 for below example, but the behavior seems to have existed since Magento CE 1.6+.

Steps to reproduce

This can be reproduced with deletion of any entity in an upgrade script, but here is one example:

  1. Create a new customer group.
  2. Add product prices and catalog price rules that use this customer group.
  3. Attempt to delete the customer group(s) in an upgrade script. Example:
$setup->startSetup();
...
$this->groupRepository->delete($customerGroup);
...
$setup->endSetup();

Expected result

The customer group is deleted, along with all database entries that have a foreign key on this customer group. This includes entries in tables like catalog_product_price_index, catalog_product_index_price_idx, catalogrule_customer_group and salesrule_customer_group, among others.

Actual result

The customer group is deleted, but entries remain in the above tables with foreign keys, causing severe downstream issues. Using the above example, deleting a customer group causes errors when saving products because a foreign key constraint fails:

SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`catalogrule_group_website`, CONSTRAINT `CATRULE_GROUP_WS_CSTR_GROUP_ID_CSTR_GROUP_CSTR_GROUP_ID` FOREIGN KEY (`customer_group_id`) REFERENCES `customer_group` (`customer_group_id`), query was: INSERT INTO `catalogrule_group_website` (`rule_id`, `customer_group_id`, `website_id`) SELECT DISTINCT  `catalogrule_product`.`rule_id`, `catalogrule_product`.`customer_group_id`, `catalogrule_product`.`website_id` FROM `catalogrule_product` WHERE (1495049620 >= from_time AND ((1495049620 <= to_time AND to_time > 0) OR to_time = 0)) ON DUPLICATE KEY UPDATE `rule_id` = VALUES(`rule_id`), `customer_group_id` = VALUES(`customer_group_id`), `website_id` = VALUES(`website_id`)

Root Cause

The issue is ultimately due to this code:

// \Magento\Framework\DB\Adapter\Pdo\Mysql::startSetup
public function startSetup()
{
	...
	$this->rawQuery("SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0");
	...
}

// \Magento\Framework\DB\Adapter\Pdo\Mysql::endSetup
public function endSetup()
{
	...
	$this->rawQuery("SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS=0, 0, 1)");
	...
}

startSetup disables foreign key checks.

Workaround

Enable foreign key checks before deleting the entities in the upgrade script:

...
$setup->getConnection()->query('SET @TEMPORARY_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=1');
$this->groupRepository->delete($customerGroup);
$setup->getConnection()->query('SET FOREIGN_KEY_CHECKS=IF(@TEMPORARY_FOREIGN_KEY_CHECKS=0, 0, 1)');
...

Summary

It seems that disabling foreign key checks should be the responsibility of the developer writing the upgrade script, because it would be immediately obvious that they would need to do so to get their script to complete. With the current behavior, unaware developers can delete data with foreign keys disabled, possibly causing severe issues that are not immediately noticeable and are far downstream from the root cause.

This unexpected behavior can cause severe issues and should be discussed. If it is not possible to modify this behavior, an explanation would be appreciated.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Issue: Clear DescriptionGate 2 Passed. Manual verification of the issue description passedIssue: ConfirmedGate 3 Passed. Manual verification of the issue completed. Issue is confirmedIssue: Format is validGate 1 Passed. Automatic verification of issue format passedIssue: Ready for WorkGate 4. Acknowledged. Issue is added to backlog and ready for developmentReproduced on 2.1.xThe issue has been reproduced on latest 2.1 releaseReproduced on 2.2.xThe issue has been reproduced on latest 2.2 releaseReproduced on 2.3.xThe issue has been reproduced on latest 2.3 release

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions