Problem/Motivation

Migrations have required migration_dependencies to indicate when one has a hard dependency on another - for example, a term migration should be run before a node migration that references those terms. MigrateExecutable::import() enforces this by calling checkRequirements() at the beginning of an import operation, which among other things makes sure all the dependent migrations have processed all their source rows.

Rollback should be doing the same thing - since things should be deleted in the reverse order they were imported, each migration should check that all migrations which depend on it have already been rolled back (specifically, that their processed count is 0).

Proposed resolution

Add a checkRollbackRequirements() method to the Migration plugin and MigrationInterface, which is the flip side of checkRequirements - verifying that "later" migrations have no processed rows remaining and throwing RequirementsException if verification fails. MigrateExecutable::rollback() should catch the exception and return MigrationInterface::RESULT_FAILED.

Remaining tasks

Write a fail test (rollback a migration when another migration dependent on it has not been rolled back).

User interface changes

N/A

API changes

checkRollbackRequirements() added to MigrationInterface. This is a BC break and needs careful consideration. In practice, it's unlikely anyone is implementing their own plugin implementing MigrationInterface, so adding an implementation to the Migration plugin class should prevent anything from breaking in the real world.

Data model changes

N/A

Original issue summary

When running migrate rollback operations you can get your database in inconsistent state.

This may happen on two reasons:

First, migrations are arranged by group and this breaks dependencies. See https://www.drupal.org/node/2830357, it needs to be resolved.

Second, when running migration rollbacks, if some migration fails the rollback process ignores this and just CONTINUES. In this case, the subsequent migration on which the failed one depends on, would be rolled back which could bring two major problems:

1) the failed migration could be unable to rollback ever.
2) any further migration imports could be impossible.

Example:
Let's put migration A_child depends on migration B_parent.
And A_child creates entities of type A which reference entities created by B_parent (A -> B)
Now let's set A_child status to some not-Idle value by running its import and immediately stopping it for example.
Now let's rollback both with `drush mr --all` for example.
What happens?
A_child is skipped because its status is wrong and only B_parent is rolled back.

Now what we have in the db? Right, A entities now reference to non-existing B entities.

CommentFileSizeAuthor
#2 migrate_tools-2838995.patch4.72 KBOnkelTem
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

OnkelTem created an issue. See original summary.

OnkelTem’s picture

Status: Active » Needs review
FileSize
4.72 KB

Attaching a patch.

It adds tracking of result statues of rollback operations and prevents running rollbacks of "parent" migrations if "children" ones failed.

NOTE: The patch is created from a branch with this patch applied first: https://www.drupal.org/node/2830357

mikeryan’s picture

Title: Migrate rollback may break database integrity » Rollback does not verify dependent migrations have been rolled back
Project: Migrate Tools » Drupal core
Version: 8.x-3.x-dev » 8.3.x-dev
Component: Drush commands » migration system
Issue summary: View changes
Status: Needs review » Active

The base problem here is that the core rollback() support does not verify dependencies are complete on rollback() as it does for import() - moving to the core queue to deal with that.

Now what we have in the db? Right, A entities now reference to non-existing B entities.

Actually, I don't believe there's a data integrity issue here - the deletion of the B entities should remove all references to them (e.g., if you manually delete a term through the UI, then any entity references to that term by all nodes will be removed).

mikeryan’s picture

Issue tags: +Migrate BC break

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

heddn’s picture

Category: Bug report » Feature request
Issue tags: -Migrate BC break

I think we agree that adding things to the interface would be a BC break. But does this *have* to happen? Is this going to block migrate going stable? We can always add another RollbackableInterface or such at a later date and do an instance_of check. It isn't pretty, but it would work.

So, I'm removing the BC break tag. And I'm also marking this as a feature, not a bug. Again, this is a nice to have. If you *really* need to rollback, drop the database, truncate tables, do a fresh install. My point is, there are work arounds.

freelock’s picture

Just adding a couple scenarios we've hit with this -- largely related to multiple migrations targeting the same entities.

I know there's an issue related to D6 term_node migrations getting rolled into the main migration -- term_node migrations currently target the same nodes that were previously migrated by a node migration. When I last worked with this, it ended up being extremely dangerous -- if you rolled back a term_node migration, it deleted the entire nodes that were actually created during the node_migration. That suggests we need to do away with the term_node migrations before this issue could work -- #2597650: Term references should be incorporated into D6 node migration.

But we have an entirely custom migration that relies on this ability to work as well -- we are migrating in data from several different CSV files, some of which essentially are getting added to the original entities as multiple values of a field. We modeled this on the term_node migration, and it works great for helping to normalize the data into something that works well with Drupal.

I guess for these types of migration, the only answer I can think of is "you can't reliably roll back one of these migrations." You have to roll back all, or you end up with missing entities. So if there is a dependency requirement for rolling back, it needs to consider this scenario, and not leave us in a state where we can't roll back all the migrations that overload an entity.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

m.stenta’s picture

Version: 8.9.x-dev » 9.3.x-dev

Bumping this to 9.3.x - encountering this in testing the farmOS 2.x migrations. Not critical, but makes rollbacks harder because we're using Entity Reference Integrity to prevent entities from being deleted if other entities reference them.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.