このトピックでは、[DELETE CASCADE]
や [UPDATE CASCADE]
など、ソースデータベースの外部キー制約によって引き起こされるデータの不整合を回避する方法について説明します。
背景情報
外部キー制約があるMySQLデータベースの親テーブルのデータを削除または更新すると ([削除]
、[更新]
など) 、子テーブルの関連データは自動的に削除または更新されます。 これらの子テーブルのデータを自動的に削除または更新する操作は、バイナリログに記録されません。
影響
Data Transmission Service (DTS) を使用して、外部キーの制約があるソースデータベース内の増分データを移行、同期、または追跡する場合、DTSはバイナリログから特定の削除または更新操作を取得できません。 これにより、データの不整合やデータ損失が発生する可能性があります。 例えば、子テーブルのデータ量が、移動先データベースの親テーブルのデータ量よりも多い場合がある。
シナリオ
ソースデータベースのデータベースタイプは、MySQL、PolarDB for MySQL、MariaDB、PolarDB-X 1.0、PolarDB-X 2.0、またはOceanBase (MySQL)です。
解決策
このセクションでは、外部キーの制約によって引き起こされるデータの不整合を回避するために、削除および更新操作を手動で管理する方法、またはトリガーを使用する方法について説明します。
データ管理 (DMS) で次のSQL文を実行することを推奨します。 他のMySQLクライアントでSQL文を実行すると、結果が異なる場合があります。
サンプルコード
親テーブルの作成
-- Create a parent table.
CREATE TABLE parent (
id INT PRIMARY KEY,
name VARCHAR(50)
);
-- Insert data.
INSERT INTO parent (id, name) VALUES (1, 'Parent 1'), (2, 'Parent 2');
子テーブルの作成
-- Create a child table with the foreign key constraint FOREIGN KEY REFERENCES ON DELETE CASCADE.
CREATE TABLE child (
id INT PRIMARY KEY,
parent_id INT,
name VARCHAR(50),
FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE ON UPDATE CASCADE
);
-- Insert data.
INSERT INTO child (id, parent_id, name) VALUES (1, 1, 'Child 1'), (2, 1, 'Child 2'), (3, 2, 'Child 3');
手順
削除および更新操作を手動で管理する
親テーブルのデータを削除または更新する前に、子テーブルの関連データを手動で削除または更新できます。 これにより、すべての削除および更新操作がバイナリログに記録されます。 サンプルコード:
-- Manually delete the related record in the child table when a record in the parent table is deleted.
DELETE FROM child WHERE parent_id = 1;
DELETE FROM parent WHERE id = 1;
-- Manually update the related record in the child table when a record in the parent table is updated.
UPDATE parent SET id = 3 WHERE id = 2;
UPDATE child SET parent_id = 3 WHERE parent_id = 2;
トリガーの使用
親テーブルのデータが削除または更新されたときに、MySQLトリガーを使用して、子テーブルの関連データを自動的に削除または更新できます。 これにより、すべての削除および更新操作がバイナリログに記録されます。 サンプルコード:
-- Create a trigger.
DELIMITER //
CREATE TRIGGER delete_parent_trigger
BEFORE DELETE ON parent
FOR EACH ROW
BEGIN
DELETE FROM child WHERE parent_id = OLD.id;
END //
CREATE TRIGGER update_parent_trigger
AFTER UPDATE ON parent
FOR EACH ROW
BEGIN
UPDATE child SET parent_id = NEW.id WHERE parent_id = OLD.id;
END //
DELIMITER ;
-- Insert data.
INSERT INTO parent (id, name) VALUES (3, 'Parent 3');
INSERT INTO child (id, parent_id, name) VALUES (4, 3, 'Child 4');
-- Delete data from the parent table.
DELETE FROM parent WHERE id = 3;
-- Insert data and update.
INSERT INTO parent (id, name) VALUES (4, 'Parent 4');
INSERT INTO child (id, parent_id, name) VALUES (5, 4, 'Child 5');
UPDATE parent SET id = 5 WHERE id = 4;
概要
削除および更新操作を手動で管理するか、トリガーを使用して、[foreign key REFERENCES ON delete CASCADE]
や [FOREIGN KEY REFERENCES ON update CASCADE]
などのソースMySQLデータベースの外部キー制約によってトリガーされる削除および更新操作が、DTSインスタンスの実行中にバイナリログに正確に記録されます。