v8.5.6: dm experimentally supports foreign key#22616
v8.5.6: dm experimentally supports foreign key#22616alastori wants to merge 3 commits intopingcap:masterfrom
Conversation
Update four docs pages to reflect DM's experimental FK support shipping in v8.5.6 (PRs pingcap#12351, pingcap#12414, pingcap#12329). All behaviors validated against a live build (v8.5.5-12-gd6d53adbe, 13 test scenarios, all passing). dm/dm-safe-mode.md: - Add "Foreign key handling (experimental)" section with three subsections: non-key UPDATE optimization, session-level foreign_key_checks toggle, and multi-worker FK causality - Add forward-reference from Working principle section to FK handling - Document PK/UK guardrail: task pauses, not silent cascade dm/dm-compatibility-catalog.md: - Rename section from "Incompatibility with foreign key CASCADE operations" to "Foreign key CASCADE operations" - Add experimental support description with safe mode and causality details - List validated constraints: PK/UK guardrail, DDL rejection, routing limitation, BAL ancestor requirement, ON UPDATE CASCADE mismatch - Preserve pre-v8.5.6 behavior description for older versions dm/dm-precheck.md: - Update FK warning: TiDB supports FKs (GA since v8.5.0), DM has experimental support since v8.5.6. Link to compatibility catalog. foreign-key.md: - Replace blanket "DM does not support foreign keys" with experimental v8.5.6 support, warning block, and backward-compat note
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request updates the documentation for DM (Data Migration) to introduce and explain the experimental support for foreign keys in version 8.5.6. The changes detail how DM now handles foreign key constraints, including optimizations for safe mode and multi-worker causality, along with important limitations and compatibility notes, providing users with comprehensive information on this new capability. Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request updates the documentation to include experimental support for foreign keys in DM v8.5.6. The changes are well-structured across four documents, covering compatibility, pre-checks, safe mode behavior, and general foreign key information. My review focuses on improving clarity and adhering to the documentation style guide, particularly by using active voice and addressing the user in the second person. I have provided several suggestions to make the text more direct and easier for users to understand.
dm/dm-compatibility-catalog.md
Outdated
| | MariaDB > 10.5.10 | Not tested | Expected to work in most cases after bypassing the [precheck](/dm/dm-precheck.md). See [MariaDB notes](#mariadb-notes). | | ||
|
|
||
| ### Incompatibility with foreign key CASCADE operations | ||
| ### Foreign key CASCADE operations |
dm/dm-compatibility-catalog.md
Outdated
| > - Table routing combined with `worker-count > 1` is not supported. Set `worker-count=1` when using routing with foreign key tables. | ||
| > - The block-allow-list must include all ancestor tables in the foreign key chain. Filtered ancestor tables cause the task to pause with an error during incremental sync. | ||
| > - Source and downstream foreign key metadata must match. If a mismatch is detected, use `binlog-schema update --from-target` to resync. |
There was a problem hiding this comment.
To improve clarity and adhere to the style guide (#22), I suggest rephrasing these instructions to address the user directly.
| > - Table routing combined with `worker-count > 1` is not supported. Set `worker-count=1` when using routing with foreign key tables. | |
| > - The block-allow-list must include all ancestor tables in the foreign key chain. Filtered ancestor tables cause the task to pause with an error during incremental sync. | |
| > - Source and downstream foreign key metadata must match. If a mismatch is detected, use `binlog-schema update --from-target` to resync. | |
| - Table routing combined with `worker-count > 1` is not supported. When using table routing with foreign key tables, you must set `worker-count` to `1`. | |
| - Your block-allow-list must include all ancestor tables in the foreign key chain. If you filter out ancestor tables, the task pauses with an error during incremental sync. | |
| - Your source and downstream foreign key metadata must match. If you detect a mismatch, use `binlog-schema update --from-target` to resync. |
References
- Documentation should address users in the second person ('you'). (link)
dm/dm-precheck.md
Outdated
| - Compatibility of the upstream MySQL table schema | ||
|
|
||
| - Check whether the upstream tables have foreign keys, which are not supported by TiDB. A warning is returned if a foreign key is found in the precheck. | ||
| - Check whether the upstream tables have foreign keys. TiDB supports foreign keys (GA since v8.5.0), and DM has experimental support for replicating tables with foreign key constraints starting from v8.5.6. A warning is returned if a foreign key is found in the precheck. For details on supported scenarios and limitations, see [DM Compatibility Catalog](/dm/dm-compatibility-catalog.md#foreign-key-cascade-operations). |
There was a problem hiding this comment.
For consistency with other items in this list, this should start with "Checks". Also, using active voice makes the sentence clearer.
| - Check whether the upstream tables have foreign keys. TiDB supports foreign keys (GA since v8.5.0), and DM has experimental support for replicating tables with foreign key constraints starting from v8.5.6. A warning is returned if a foreign key is found in the precheck. For details on supported scenarios and limitations, see [DM Compatibility Catalog](/dm/dm-compatibility-catalog.md#foreign-key-cascade-operations). | |
| - Checks whether the upstream tables have foreign keys. TiDB supports foreign keys (GA since v8.5.0), and DM has experimental support for replicating tables with foreign key constraints starting from v8.5.6. DM returns a warning if it finds a foreign key in the precheck. For details on supported scenarios and limitations, see [DM Compatibility Catalog](/dm/dm-compatibility-catalog.md#foreign-key-cascade-operations). |
References
- Prefer active voice for clarity. (link)
dm/dm-safe-mode.md
Outdated
|
|
||
| * `INSERT` statements are rewritten to `REPLACE` statements. | ||
| * `UPDATE` statements are analyzed to obtain the value of the primary key or the unique index of the row updated. `UPDATE` statements are then rewritten to `DELETE` + `REPLACE` statements in the following two steps: DM deletes the old record using the primary key or unique index, and inserts the new record using the `REPLACE` statement. | ||
| * `UPDATE` statements are analyzed to obtain the value of the primary key or the unique index of the row updated. `UPDATE` statements are then rewritten to `DELETE` + `REPLACE` statements in the following two steps: DM deletes the old record using the primary key or unique index, and inserts the new record using the `REPLACE` statement. Starting from v8.5.6, when the task session sets `foreign_key_checks=1`, DM skips the `DELETE` step for `UPDATE` statements that do not change any primary key or unique key value. See [Foreign key handling](#foreign-key-handling-experimental) for details. |
There was a problem hiding this comment.
The style guide (#22) recommends addressing the user in the second person ("you"). This change makes the sentence more direct.
| * `UPDATE` statements are analyzed to obtain the value of the primary key or the unique index of the row updated. `UPDATE` statements are then rewritten to `DELETE` + `REPLACE` statements in the following two steps: DM deletes the old record using the primary key or unique index, and inserts the new record using the `REPLACE` statement. Starting from v8.5.6, when the task session sets `foreign_key_checks=1`, DM skips the `DELETE` step for `UPDATE` statements that do not change any primary key or unique key value. See [Foreign key handling](#foreign-key-handling-experimental) for details. | |
| * `UPDATE` statements are analyzed to obtain the value of the primary key or the unique index of the row updated. `UPDATE` statements are then rewritten to `DELETE` + `REPLACE` statements in the following two steps: DM deletes the old record using the primary key or unique index, and inserts the new record using the `REPLACE` statement. Starting from v8.5.6, when you set `foreign_key_checks=1` in the task session, DM skips the `DELETE` step for `UPDATE` statements that do not change any primary key or unique key value. See [Foreign key handling](#foreign-key-handling-experimental) for details. |
References
- Documentation should address users in the second person ('you'). (link)
dm/dm-safe-mode.md
Outdated
| > | ||
| > This feature is available starting from v8.5.6 and is experimental. | ||
|
|
||
| When safe mode is enabled and the downstream task session sets `foreign_key_checks=1`, the standard `DELETE` + `REPLACE` rewrite for `UPDATE` statements can trigger unintended `ON DELETE CASCADE` side effects on child rows. Starting from v8.5.6, DM includes two improvements to address this: |
There was a problem hiding this comment.
The style guide (#22) recommends addressing the user in the second person ("you"). This change makes the sentence more direct and active.
| When safe mode is enabled and the downstream task session sets `foreign_key_checks=1`, the standard `DELETE` + `REPLACE` rewrite for `UPDATE` statements can trigger unintended `ON DELETE CASCADE` side effects on child rows. Starting from v8.5.6, DM includes two improvements to address this: | |
| When you enable safe mode and set `foreign_key_checks=1` in the downstream task session, the standard `DELETE` + `REPLACE` rewrite for `UPDATE` statements can trigger unintended `ON DELETE CASCADE` side effects on child rows. Starting from v8.5.6, DM includes two improvements to address this: |
References
- Documentation should address users in the second person ('you'). (link)
dm/dm-safe-mode.md
Outdated
|
|
||
| When safe mode is enabled and the downstream task session sets `foreign_key_checks=1`, the standard `DELETE` + `REPLACE` rewrite for `UPDATE` statements can trigger unintended `ON DELETE CASCADE` side effects on child rows. Starting from v8.5.6, DM includes two improvements to address this: | ||
|
|
||
| ### Non-key UPDATE optimization |
dm/dm-safe-mode.md
Outdated
| > | ||
| > `UPDATE` statements that change primary key or unique key values are rejected by a guardrail when `foreign_key_checks=1`. The task pauses with the error: `safe-mode update with foreign_key_checks=1 and PK/UK changes is not supported`. To replicate PK/UK-changing UPDATEs on tables with foreign keys, use `safe-mode: false`. | ||
|
|
||
| ### Session-level foreign_key_checks |
There was a problem hiding this comment.
foreign-key.md
Outdated
| <CustomContent platform="tidb"> | ||
|
|
||
| - [DM](/dm/dm-overview.md) does not support foreign keys. DM disables the [`foreign_key_checks`](/system-variables.md#foreign_key_checks) of the downstream TiDB when replicating data to TiDB. Therefore, the cascading operations caused by foreign keys are not replicated from the upstream to the downstream, which might cause data inconsistency. | ||
| - [DM](/dm/dm-overview.md): Starting from v8.5.6, DM has experimental support for replicating tables with foreign key constraints. In safe mode, DM sets `foreign_key_checks=0` per batch and skips the redundant `DELETE` for non-key `UPDATE` rewrites, preventing unintended `ON DELETE CASCADE` side effects on child rows. When using `worker-count > 1`, DM discovers foreign key relations at task start and injects causality keys so that parent row operations complete before dependent child row operations. For limitations and configuration details, see [DM Safe Mode](/dm/dm-safe-mode.md#foreign-key-handling-experimental) and [DM Compatibility Catalog](/dm/dm-compatibility-catalog.md#foreign-key-cascade-operations). |
There was a problem hiding this comment.
The style guide (#22) recommends addressing the user in the second person ("you").
| - [DM](/dm/dm-overview.md): Starting from v8.5.6, DM has experimental support for replicating tables with foreign key constraints. In safe mode, DM sets `foreign_key_checks=0` per batch and skips the redundant `DELETE` for non-key `UPDATE` rewrites, preventing unintended `ON DELETE CASCADE` side effects on child rows. When using `worker-count > 1`, DM discovers foreign key relations at task start and injects causality keys so that parent row operations complete before dependent child row operations. For limitations and configuration details, see [DM Safe Mode](/dm/dm-safe-mode.md#foreign-key-handling-experimental) and [DM Compatibility Catalog](/dm/dm-compatibility-catalog.md#foreign-key-cascade-operations). | |
| - [DM](/dm/dm-overview.md): Starting from v8.5.6, DM has experimental support for replicating tables with foreign key constraints. In safe mode, DM sets `foreign_key_checks=0` per batch and skips the redundant `DELETE` for non-key `UPDATE` rewrites, preventing unintended `ON DELETE CASCADE` side effects on child rows. When you use `worker-count > 1`, DM discovers foreign key relations at task start and injects causality keys so that parent row operations complete before dependent child row operations. For limitations and configuration details, see [DM Safe Mode](/dm/dm-safe-mode.md#foreign-key-handling-experimental) and [DM Compatibility Catalog](/dm/dm-compatibility-catalog.md#foreign-key-cascade-operations). |
References
- Documentation should address users in the second person ('you'). (link)
foreign-key.md
Outdated
|
|
||
| > **Warning:** | ||
| > | ||
| > This feature is experimental. `UPDATE` statements that change primary key or unique key values in safe mode are rejected when `foreign_key_checks=1` (the task pauses). DDL operations that create, alter, or drop foreign key constraints during replication are also rejected. For the full list of constraints, see [DM Compatibility Catalog](/dm/dm-compatibility-catalog.md#foreign-key-cascade-operations). |
There was a problem hiding this comment.
Using active voice ("DM rejects...") is clearer and more direct than passive voice.
| > This feature is experimental. `UPDATE` statements that change primary key or unique key values in safe mode are rejected when `foreign_key_checks=1` (the task pauses). DDL operations that create, alter, or drop foreign key constraints during replication are also rejected. For the full list of constraints, see [DM Compatibility Catalog](/dm/dm-compatibility-catalog.md#foreign-key-cascade-operations). | |
| > This feature is experimental. DM rejects `UPDATE` statements that change primary key or unique key values in safe mode when `foreign_key_checks=1` (the task pauses). DDL operations that create, alter, or drop foreign key constraints during replication are also rejected. For the full list of constraints, see [DM Compatibility Catalog](/dm/dm-compatibility-catalog.md#foreign-key-cascade-operations). |
References
- Prefer active voice for clarity. (link)
foreign-key.md
Outdated
| > | ||
| > This feature is experimental. `UPDATE` statements that change primary key or unique key values in safe mode are rejected when `foreign_key_checks=1` (the task pauses). DDL operations that create, alter, or drop foreign key constraints during replication are also rejected. For the full list of constraints, see [DM Compatibility Catalog](/dm/dm-compatibility-catalog.md#foreign-key-cascade-operations). | ||
|
|
||
| In versions earlier than v8.5.6, DM does not support foreign keys and disables [`foreign_key_checks`](/system-variables.md#foreign_key_checks) when replicating data to TiDB. Cascading operations are not replicated from upstream to downstream, which might cause data inconsistency. |
There was a problem hiding this comment.
This rephrasing adds a bit more context and improves the flow from the previous sentence.
| In versions earlier than v8.5.6, DM does not support foreign keys and disables [`foreign_key_checks`](/system-variables.md#foreign_key_checks) when replicating data to TiDB. Cascading operations are not replicated from upstream to downstream, which might cause data inconsistency. | |
| In versions earlier than v8.5.6, DM does not support foreign keys and disables [`foreign_key_checks`](/system-variables.md#foreign_key_checks) when replicating data to TiDB. This means that cascading operations from the upstream are not replicated to the downstream, which might cause data inconsistency. |
References
- Improve clarity and readability. (link)
All 10 suggestions accepted:
- Sentence case headings with backticks for SQL keywords/variables:
CASCADE, UPDATE, foreign_key_checks
- Second person ("you") in constraint bullets, safe mode intro,
and foreign-key.md DM section
- Active voice: "DM returns/rejects" instead of passive "is returned"
- Bridge sentence for pre-v8.5.6 backward compat note
|
/retest-required |
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
|
@OliverS929: adding LGTM is restricted to approvers and reviewers in OWNERS files. DetailsIn response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
| - Compatibility of the upstream MySQL table schema | ||
|
|
||
| - Check whether the upstream tables have foreign keys, which are not supported by TiDB. A warning is returned if a foreign key is found in the precheck. | ||
| - Checks whether the upstream tables have foreign keys. TiDB supports foreign keys (GA since v8.5.0), and DM has experimental support for replicating tables with foreign key constraints starting from v8.5.6. DM returns a warning if it finds a foreign key in the precheck. For details on supported scenarios and limitations, see [DM Compatibility Catalog](/dm/dm-compatibility-catalog.md#foreign-key-cascade-operations). |
There was a problem hiding this comment.
| - Checks whether the upstream tables have foreign keys. TiDB supports foreign keys (GA since v8.5.0), and DM has experimental support for replicating tables with foreign key constraints starting from v8.5.6. DM returns a warning if it finds a foreign key in the precheck. For details on supported scenarios and limitations, see [DM Compatibility Catalog](/dm/dm-compatibility-catalog.md#foreign-key-cascade-operations). | |
| - Check whether the upstream tables have foreign keys. TiDB supports foreign keys (GA since v8.5.0), and DM provides experimental support for replicating tables with foreign key constraints starting from v8.5.6. During the precheck, DM returns a warning if foreign keys are detected. For supported scenarios and limitations, see [DM Compatibility Catalog](/dm/dm-compatibility-catalog.md#foreign-key-cascade-operations). |
| <CustomContent platform="tidb"> | ||
|
|
||
| - [DM](/dm/dm-overview.md) does not support foreign keys. DM disables the [`foreign_key_checks`](/system-variables.md#foreign_key_checks) of the downstream TiDB when replicating data to TiDB. Therefore, the cascading operations caused by foreign keys are not replicated from the upstream to the downstream, which might cause data inconsistency. | ||
| - [DM](/dm/dm-overview.md): Starting from v8.5.6, DM has experimental support for replicating tables with foreign key constraints. In safe mode, DM sets `foreign_key_checks=0` per batch and optimizes non-key `UPDATE` rewrites to prevent unintended `ON DELETE CASCADE` side effects. When you use `worker-count > 1`, DM injects causality keys so that parent row operations complete before child row operations. This feature is experimental; DM rejects PK/UK-changing UPDATEs and FK-related DDL in safe mode. For the full list of constraints, see [DM Safe Mode](/dm/dm-safe-mode.md#foreign-key-handling-experimental) and [DM Compatibility Catalog](/dm/dm-compatibility-catalog.md#foreign-key-cascade-operations). In versions earlier than v8.5.6, DM disables [`foreign_key_checks`](/system-variables.md#foreign_key_checks) when replicating data to TiDB, so cascading operations are not replicated from upstream to downstream. |
There was a problem hiding this comment.
| - [DM](/dm/dm-overview.md): Starting from v8.5.6, DM has experimental support for replicating tables with foreign key constraints. In safe mode, DM sets `foreign_key_checks=0` per batch and optimizes non-key `UPDATE` rewrites to prevent unintended `ON DELETE CASCADE` side effects. When you use `worker-count > 1`, DM injects causality keys so that parent row operations complete before child row operations. This feature is experimental; DM rejects PK/UK-changing UPDATEs and FK-related DDL in safe mode. For the full list of constraints, see [DM Safe Mode](/dm/dm-safe-mode.md#foreign-key-handling-experimental) and [DM Compatibility Catalog](/dm/dm-compatibility-catalog.md#foreign-key-cascade-operations). In versions earlier than v8.5.6, DM disables [`foreign_key_checks`](/system-variables.md#foreign_key_checks) when replicating data to TiDB, so cascading operations are not replicated from upstream to downstream. | |
| - [DM](/dm/dm-overview.md): starting from v8.5.6, DM provides experimental support for replicating tables that use foreign key constraints. For supported scenarios and limitations, see [DM Compatibility Catalog](/dm/dm-compatibility-catalog.md#foreign-key-cascade-operations). In versions earlier than v8.5.6, DM disables the [`foreign_key_checks`](/system-variables.md#foreign_key_checks) system variable when replicating data to TiDB, so cascading operations are not replicated to the downstream cluster. |
|
|
||
| * `INSERT` statements are rewritten to `REPLACE` statements. | ||
| * `UPDATE` statements are analyzed to obtain the value of the primary key or the unique index of the row updated. `UPDATE` statements are then rewritten to `DELETE` + `REPLACE` statements in the following two steps: DM deletes the old record using the primary key or unique index, and inserts the new record using the `REPLACE` statement. | ||
| * `UPDATE` statements are analyzed to obtain the value of the primary key or the unique index of the row updated. `UPDATE` statements are then rewritten to `DELETE` + `REPLACE` statements in the following two steps: DM deletes the old record using the primary key or unique index, and inserts the new record using the `REPLACE` statement. Starting from v8.5.6, when you set `foreign_key_checks=1` in the task session, DM skips the `DELETE` step for `UPDATE` statements that do not change any primary key or unique key value. See [Foreign key handling](#foreign-key-handling-experimental) for details. |
There was a problem hiding this comment.
| * `UPDATE` statements are analyzed to obtain the value of the primary key or the unique index of the row updated. `UPDATE` statements are then rewritten to `DELETE` + `REPLACE` statements in the following two steps: DM deletes the old record using the primary key or unique index, and inserts the new record using the `REPLACE` statement. Starting from v8.5.6, when you set `foreign_key_checks=1` in the task session, DM skips the `DELETE` step for `UPDATE` statements that do not change any primary key or unique key value. See [Foreign key handling](#foreign-key-handling-experimental) for details. | |
| * `UPDATE` statements are analyzed to obtain the value of the primary key or the unique index of the row updated. `UPDATE` statements are then rewritten to `DELETE` + `REPLACE` statements in the following two steps: DM deletes the old record using the primary key or unique index, and inserts the new record using the `REPLACE` statement. | |
| Starting from v8.5.6, when you set `foreign_key_checks=1` in the task session, DM skips the `DELETE` step for `UPDATE` statements that do not modify primary key or unique index values. For more information, see [Foreign key handling](#foreign-key-handling). |
| syncer-config-name: "global" # Name of the syncers configuration. | ||
| ``` | ||
|
|
||
| ## Foreign key handling (experimental) |
There was a problem hiding this comment.
| ## Foreign key handling (experimental) | |
| ## Foreign key handling <span class="version-mark">New in v8.5.6</span> |
| > **Note:** | ||
| > | ||
| > This feature is available starting from v8.5.6 and is experimental. |
There was a problem hiding this comment.
| > **Note:** | |
| > | |
| > This feature is available starting from v8.5.6 and is experimental. | |
| > **Warning:** | |
| > | |
| > This feature is introduced in v8.5.6 and is experimental. |
| > | ||
| > This feature is available starting from v8.5.6 and is experimental. | ||
|
|
||
| When you enable safe mode and set `foreign_key_checks=1` in the downstream task session, the standard `DELETE` + `REPLACE` rewrite for `UPDATE` statements can trigger unintended `ON DELETE CASCADE` side effects on child rows. Starting from v8.5.6, DM includes two improvements to address this: |
There was a problem hiding this comment.
| When you enable safe mode and set `foreign_key_checks=1` in the downstream task session, the standard `DELETE` + `REPLACE` rewrite for `UPDATE` statements can trigger unintended `ON DELETE CASCADE` side effects on child rows. Starting from v8.5.6, DM includes two improvements to address this: | |
| When you enable safe mode and set `foreign_key_checks=1` in the downstream task session, the default `DELETE` + `REPLACE` rewrite for `UPDATE` statements can trigger unintended `ON DELETE CASCADE` effects on child rows. Starting from v8.5.6, DM introduces the following improvements to address this issue. |
|
|
||
| ### Non-key `UPDATE` optimization | ||
|
|
||
| For `UPDATE` statements that do not change any primary key or unique key value, DM skips the `DELETE` step and emits only `REPLACE INTO`. Because the primary key is unchanged, `REPLACE INTO` overwrites the existing row without triggering a cascade delete. This optimization applies automatically in safe mode. |
There was a problem hiding this comment.
| For `UPDATE` statements that do not change any primary key or unique key value, DM skips the `DELETE` step and emits only `REPLACE INTO`. Because the primary key is unchanged, `REPLACE INTO` overwrites the existing row without triggering a cascade delete. This optimization applies automatically in safe mode. | |
| For `UPDATE` statements that do not modify primary key or unique key values, DM skips the `DELETE` step and executes only `REPLACE INTO`. Because the primary key remains unchanged, `REPLACE INTO` overwrites the existing row without triggering cascade deletes. This optimization is applied automatically in safe mode. |
|
|
||
| For `UPDATE` statements that do not change any primary key or unique key value, DM skips the `DELETE` step and emits only `REPLACE INTO`. Because the primary key is unchanged, `REPLACE INTO` overwrites the existing row without triggering a cascade delete. This optimization applies automatically in safe mode. | ||
|
|
||
| For example, given the following upstream statement where `id` is the primary key: |
There was a problem hiding this comment.
| For example, given the following upstream statement where `id` is the primary key: | |
| For example, consider the following upstream statement, where `id` is the primary key: |
| UPDATE dummydb.dummytbl SET int_value = 888999 WHERE id = 123; | ||
| ``` | ||
|
|
||
| In previous versions, safe mode rewrites this as: |
There was a problem hiding this comment.
| In previous versions, safe mode rewrites this as: | |
| In versions earlier than v8.5.6, safe mode rewrites this statement as follows: |
| In previous versions, safe mode rewrites this as: | ||
|
|
||
| ```sql | ||
| DELETE FROM dummydb.dummytbl WHERE id = 123; -- triggers ON DELETE CASCADE |
There was a problem hiding this comment.
| DELETE FROM dummydb.dummytbl WHERE id = 123; -- triggers ON DELETE CASCADE | |
| DELETE FROM dummydb.dummytbl WHERE id = 123; -- Triggers ON DELETE CASCADE |
| REPLACE INTO dummydb.dummytbl (id, int_value, ...) VALUES (123, 888999, ...); | ||
| ``` | ||
|
|
||
| Starting from v8.5.6, safe mode rewrites this as: |
There was a problem hiding this comment.
| Starting from v8.5.6, safe mode rewrites this as: | |
| Starting from v8.5.6, safe mode rewrites the statement as follows: |
| Starting from v8.5.6, safe mode rewrites this as: | ||
|
|
||
| ```sql | ||
| REPLACE INTO dummydb.dummytbl (id, int_value, ...) VALUES (123, 888999, ...); -- no cascade |
There was a problem hiding this comment.
| REPLACE INTO dummydb.dummytbl (id, int_value, ...) VALUES (123, 888999, ...); -- no cascade | |
| REPLACE INTO dummydb.dummytbl (id, int_value, ...) VALUES (123, 888999, ...); -- No cascade |
|
|
||
| > **Warning:** | ||
| > | ||
| > `UPDATE` statements that change primary key or unique key values are rejected by a guardrail when `foreign_key_checks=1`. The task pauses with the error: `safe-mode update with foreign_key_checks=1 and PK/UK changes is not supported`. To replicate PK/UK-changing UPDATEs on tables with foreign keys, use `safe-mode: false`. |
There was a problem hiding this comment.
| > `UPDATE` statements that change primary key or unique key values are rejected by a guardrail when `foreign_key_checks=1`. The task pauses with the error: `safe-mode update with foreign_key_checks=1 and PK/UK changes is not supported`. To replicate PK/UK-changing UPDATEs on tables with foreign keys, use `safe-mode: false`. | |
| > When `foreign_key_checks=1`, DM does not support `UPDATE` statements that modify primary key or unique key values. In this case, the task is paused with the error `safe-mode update with foreign_key_checks=1 and PK/UK changes is not supported`. To replicate such `UPDATE` statements on tables with foreign keys, set `safe-mode: false`. |
|
|
||
| ### Session-level `foreign_key_checks` | ||
|
|
||
| During safe mode batch execution, DM sets `SET SESSION foreign_key_checks=0` before executing `INSERT` and `UPDATE` batches, and restores the original value afterward. This prevents `REPLACE INTO` (internally `DELETE` + `INSERT`) from triggering cascade operations in the downstream. |
There was a problem hiding this comment.
| During safe mode batch execution, DM sets `SET SESSION foreign_key_checks=0` before executing `INSERT` and `UPDATE` batches, and restores the original value afterward. This prevents `REPLACE INTO` (internally `DELETE` + `INSERT`) from triggering cascade operations in the downstream. | |
| During batch execution in safe mode, DM executes `SET SESSION foreign_key_checks=0` before executing `INSERT` and `UPDATE` batches, and restores the original value afterward. This prevents `REPLACE INTO` (which internally performs `DELETE` + `INSERT`) from triggering cascade operations in the downstream. |
|
|
||
| During safe mode batch execution, DM sets `SET SESSION foreign_key_checks=0` before executing `INSERT` and `UPDATE` batches, and restores the original value afterward. This prevents `REPLACE INTO` (internally `DELETE` + `INSERT`) from triggering cascade operations in the downstream. | ||
|
|
||
| The session variable toggle adds a small overhead per batch flush (two `SET SESSION` round-trips). This overhead is negligible for most workloads. |
There was a problem hiding this comment.
| The session variable toggle adds a small overhead per batch flush (two `SET SESSION` round-trips). This overhead is negligible for most workloads. | |
| This session-level setting introduces a small overhead per batch (two `SET SESSION` round trips). In most workloads, this overhead is negligible. |
|
|
||
| ### Multi-worker foreign key causality | ||
|
|
||
| When using `worker-count > 1` with foreign key tables, DM discovers foreign key relations from the downstream `CREATE TABLE` schema at task start. For each DML operation, DM injects causality keys derived from the foreign key relationships, ensuring that parent row operations and dependent child row operations are assigned to the same DML worker queue. This preserves binlog order across workers and prevents foreign key constraint violations. |
There was a problem hiding this comment.
| When using `worker-count > 1` with foreign key tables, DM discovers foreign key relations from the downstream `CREATE TABLE` schema at task start. For each DML operation, DM injects causality keys derived from the foreign key relationships, ensuring that parent row operations and dependent child row operations are assigned to the same DML worker queue. This preserves binlog order across workers and prevents foreign key constraint violations. | |
| When you set `worker-count` to a value greater than 1 and the task includes tables with foreign keys, DM reads foreign key relationships from the downstream `CREATE TABLE` schema when the task starts. For each DML operation, DM injects causality keys based on these relationships. This ensures that operations on parent rows and their dependent child rows are assigned to the same DML worker queue. |
|
|
||
| ### Incompatibility with foreign key CASCADE operations | ||
| ### Foreign key `CASCADE` operations | ||
|
|
There was a problem hiding this comment.
| > **Warning:** | |
| > | |
| > This feature is experimental. | |
|
|
||
| - DM creates foreign key **constraints** on the target, but they are not enforced while applying transactions because DM sets the session variable [`foreign_key_checks=OFF`](/system-variables.md#foreign_key_checks). | ||
| - DM does **not** support `ON DELETE CASCADE` or `ON UPDATE CASCADE` behavior by default, and enabling `foreign_key_checks` via a DM task session variable is not recommended. If your workload relies on cascades, **do not assume** that cascade effects will be replicated. | ||
| Starting from v8.5.6, DM has **experimental** support for replicating tables with foreign key constraints. This includes two improvements: |
There was a problem hiding this comment.
| Starting from v8.5.6, DM has **experimental** support for replicating tables with foreign key constraints. This includes two improvements: | |
| Starting from v8.5.6, DM provides **experimental** support for replicating tables that use foreign key constraints. This support includes the following improvements: |
| - **Safe mode**: DM sets `foreign_key_checks=0` per batch during safe mode execution and skips the redundant `DELETE` for `UPDATE` statements that do not change primary key or unique key values. This prevents `REPLACE INTO` (internally `DELETE` + `INSERT`) from triggering unintended `ON DELETE CASCADE` side effects on child rows. For details, see [DM Safe Mode](/dm/dm-safe-mode.md#foreign-key-handling-experimental). | ||
| - **Multi-worker causality**: When `worker-count > 1`, DM discovers foreign key relations from the downstream schema at task start and injects causality keys so that parent row DML operations complete before dependent child row operations, preserving binlog order across workers. |
There was a problem hiding this comment.
| - **Safe mode**: DM sets `foreign_key_checks=0` per batch during safe mode execution and skips the redundant `DELETE` for `UPDATE` statements that do not change primary key or unique key values. This prevents `REPLACE INTO` (internally `DELETE` + `INSERT`) from triggering unintended `ON DELETE CASCADE` side effects on child rows. For details, see [DM Safe Mode](/dm/dm-safe-mode.md#foreign-key-handling-experimental). | |
| - **Multi-worker causality**: When `worker-count > 1`, DM discovers foreign key relations from the downstream schema at task start and injects causality keys so that parent row DML operations complete before dependent child row operations, preserving binlog order across workers. | |
| - **Safe mode**: during safe mode execution, DM sets `foreign_key_checks=0` for each batch and skips the redundant `DELETE` step for `UPDATE` statements that do not modify primary key or unique key values. This prevents `REPLACE INTO` (which internally performs `DELETE` + `INSERT`) from triggering unintended `ON DELETE CASCADE` effects on child rows. For details, see [DM Safe Mode](/dm/dm-safe-mode.md#foreign-key-handling). | |
| - **Multi-worker causality**: when `worker-count > 1`, DM reads foreign key relationships from the downstream schema at task start and injects causality keys. This ensures that DML operations on parent rows complete before operations on dependent child rows, preserving binlog order across workers. |
| > - Your source and downstream foreign key metadata must match. If you detect a mismatch, use `binlog-schema update --from-target` to resync. | ||
| > - `ON UPDATE CASCADE` is not replicated correctly in safe mode when the `UPDATE` changes a primary key or unique key value. DM rewrites such UPDATEs as `DELETE` + `REPLACE`, which would trigger `ON DELETE` actions instead of `ON UPDATE` actions. The guardrail rejects the PK/UK change and pauses the task. Non-key `UPDATE` statements on tables with `ON UPDATE CASCADE` replicate without issues. | ||
|
|
||
| In versions earlier than v8.5.6, DM creates foreign key constraints on the target but does not enforce them because it sets the session variable [`foreign_key_checks=OFF`](/system-variables.md#foreign_key_checks). Cascading operations are not replicated, so do not assume that cascade effects will be applied in the downstream. |
There was a problem hiding this comment.
| In versions earlier than v8.5.6, DM creates foreign key constraints on the target but does not enforce them because it sets the session variable [`foreign_key_checks=OFF`](/system-variables.md#foreign_key_checks). Cascading operations are not replicated, so do not assume that cascade effects will be applied in the downstream. | |
| In versions earlier than v8.5.6, DM creates foreign key constraints in the downstream but does not enforce them because it sets the session variable [`foreign_key_checks=OFF`](/system-variables.md#foreign_key_checks). As a result, cascading operations are not replicated to the downstream. |
| > **Warning:** | ||
| > | ||
| > This feature is experimental. The following constraints apply: | ||
| > | ||
| > - `UPDATE` statements that change primary key or unique key values in safe mode are rejected. The task pauses with the error: `safe-mode update with foreign_key_checks=1 and PK/UK changes is not supported`. To replicate these UPDATEs, use `safe-mode: false`. | ||
| > - DDL operations that create, alter, or drop foreign key constraints during replication are rejected when `foreign_key_checks=1`. | ||
| > - Table routing combined with `worker-count > 1` is not supported. When using table routing with foreign key tables, you must set `worker-count` to `1`. | ||
| > - Your block-allow-list must include all ancestor tables in the foreign key chain. If you filter out ancestor tables, the task pauses with an error during incremental sync. | ||
| > - Your source and downstream foreign key metadata must match. If you detect a mismatch, use `binlog-schema update --from-target` to resync. | ||
| > - `ON UPDATE CASCADE` is not replicated correctly in safe mode when the `UPDATE` changes a primary key or unique key value. DM rewrites such UPDATEs as `DELETE` + `REPLACE`, which would trigger `ON DELETE` actions instead of `ON UPDATE` actions. The guardrail rejects the PK/UK change and pauses the task. Non-key `UPDATE` statements on tables with `ON UPDATE CASCADE` replicate without issues. |
There was a problem hiding this comment.
| > **Warning:** | |
| > | |
| > This feature is experimental. The following constraints apply: | |
| > | |
| > - `UPDATE` statements that change primary key or unique key values in safe mode are rejected. The task pauses with the error: `safe-mode update with foreign_key_checks=1 and PK/UK changes is not supported`. To replicate these UPDATEs, use `safe-mode: false`. | |
| > - DDL operations that create, alter, or drop foreign key constraints during replication are rejected when `foreign_key_checks=1`. | |
| > - Table routing combined with `worker-count > 1` is not supported. When using table routing with foreign key tables, you must set `worker-count` to `1`. | |
| > - Your block-allow-list must include all ancestor tables in the foreign key chain. If you filter out ancestor tables, the task pauses with an error during incremental sync. | |
| > - Your source and downstream foreign key metadata must match. If you detect a mismatch, use `binlog-schema update --from-target` to resync. | |
| > - `ON UPDATE CASCADE` is not replicated correctly in safe mode when the `UPDATE` changes a primary key or unique key value. DM rewrites such UPDATEs as `DELETE` + `REPLACE`, which would trigger `ON DELETE` actions instead of `ON UPDATE` actions. The guardrail rejects the PK/UK change and pauses the task. Non-key `UPDATE` statements on tables with `ON UPDATE CASCADE` replicate without issues. | |
| The following limitations apply to foreign key replication: | |
| - In safe mode, DM does not support `UPDATE` statements that modify primary key or unique key values. The task is paused with the error `safe-mode update with foreign_key_checks=1 and PK/UK changes is not supported`. To replicate such statements, set `safe-mode: false`. | |
| - When `foreign_key_checks=1`, DM does not support DDL statements that create, modify, or drop foreign key constraints during replication. | |
| - Table routing is not supported when `worker-count > 1`. If you use table routing with tables that include foreign keys, set `worker-count` to `1`. | |
| - The block-allow list must include all ancestor tables in the foreign key dependency chain. If ancestor tables are filtered out, the task is paused with an error during incremental replication. | |
| - Foreign key metadata must be consistent between the source and downstream. If inconsistencies are detected, run `binlog-schema update --from-target` to resynchronize metadata. | |
| - `ON UPDATE CASCADE` is not correctly replicated in safe mode when an `UPDATE` modifies primary key or unique key values. DM rewrites such statements as `DELETE` + `REPLACE`, which triggers `ON DELETE` actions instead of `ON UPDATE` actions. In this case, DM rejects the statement and pauses the task. `UPDATE` statements that do not modify key values are replicated correctly. |
Summary
v8.5.5-12-gd6d53adbe) with 13 test scenarios, all passingChanges
dm/dm-safe-mode.mddm/dm-compatibility-catalog.mddm/dm-precheck.mdforeign-key.mdRelated
Test plan
release-8.5HEAD buildrelease-8.5branch after merge