|
| 1 | +# Reverting Migrations |
| 2 | + |
| 3 | +`gh-ost` can attempt to revert a previously completed migration if the follow conditions are met: |
| 4 | +- The first `gh-ost` process was invoked with `--checkpoint` |
| 5 | +- The checkpoint table (name ends with `_ghk`) still exists |
| 6 | +- The binlogs from the time of the migration's cut-over still exist on the replica gh-ost is inspecting (specified by `--host`) |
| 7 | + |
| 8 | +To revert, find the name of the "old" table from the original migration e.g. `_mytable_del`. Then invoke `gh-ost` with the same arguments and the flags `--revert` and `--old-table="_mytable_del"`. |
| 9 | +gh-ost will read the binlog coordinates of the original cut-over from the checkpoint table and bring the old table up to date. Then it performs another cut-over to complete the reversion. |
| 10 | + |
| 11 | +> [!WARNING] |
| 12 | +> It is recommended use `--checkpoint` with `--gtid` enabled so that checkpoint binlog coordinates store GTID sets rather than file positions. In that case, `gh-ost` can revert using a different replica than it originally attached to. |
| 13 | +
|
| 14 | +### ❗ Note ❗ |
| 15 | +Reverting is roughly equivalent to applying the "reverse" migration. _Before attempting to revert you should determine if the reverse migration is possible and does not involve any unacceptable data loss._ |
| 16 | + |
| 17 | +For example: if the original migration drops a `NOT NULL` column that has no `DEFAULT` then the reverse migration adds the column. In this case, the reverse migration is impossible if rows were added after the original cut-over and the revert will fail. |
| 18 | +Another example: if the original migration modifies a `VARCHAR(32)` column to `VARCHAR(64)`, the reverse migration truncates the `VARCHAR(64)` column to `VARCHAR(32)`. If values were inserted with length > 32 after the cut-over then the revert will fail (in strict mode) or lose data (in non-strict mode). |
| 19 | + |
| 20 | + |
| 21 | +## Example |
| 22 | +The migration starts with a `gh-ost` invocation such as: |
| 23 | +```shell |
| 24 | +gh-ost \ |
| 25 | +--chunk-size=100 \ |
| 26 | +--host=replica1.company.com \ |
| 27 | +--database="mydb" \ |
| 28 | +--table="mytable" \ |
| 29 | +--alter="drop key idx1" |
| 30 | +--gtid \ |
| 31 | +--checkpoint \ |
| 32 | +--checkpoint-seconds=60 \ |
| 33 | +--execute |
| 34 | +``` |
| 35 | + |
| 36 | +In this example `gh-ost` writes a cut-over checkpoint to `_mytable_ghk` after the cut-over is successful. The original table is renamed to `_mytable_del`. |
| 37 | + |
| 38 | +Suppose that dropping the index causes problems, the migration can be revert with: |
| 39 | +```shell |
| 40 | +# revert migration |
| 41 | +gh-ost \ |
| 42 | +--chunk-size=100 \ |
| 43 | +--host=replica1.company.com \ |
| 44 | +--database="mydb" \ |
| 45 | +--table="mytable" \ |
| 46 | +--old-table="_mytable_del" |
| 47 | +--gtid \ |
| 48 | +--checkpoint \ |
| 49 | +--checkpoint-seconds=60 \ |
| 50 | +--revert |
| 51 | +--execute |
| 52 | +``` |
| 53 | + |
| 54 | +gh-ost then reconnects at the binlog coordinates stored in the cut-over checkpoint and applies DMLs until the old table is up-to-date. |
| 55 | +Note that the "reverse" migration is `ADD KEY idx(...)` so there is no potential data loss to consider. |
0 commit comments