背景資訊
在使用了外鍵約束FOREIGN KEY REFERENCES ON DELETE CASCADE
或FOREIGN KEY REFERENCES ON UPDATE CASCADE
的MySQL資料庫中,若刪除或更新父表的資料,則子表中關聯的資料將會自動被刪除或更新。在MySQL資料庫中,這些自動刪除或更新子表資料的操作不會被記錄到二進位日誌(Binlog)中。
影響
在使用Data Transmission Service進行含增量任務的資料移轉、資料同步、資料訂閱時,DTS會因無法從Binlog中擷取到這些刪除或更新操作,而無法遷移、同步、訂閱該刪除或更新操作,從而可能會導致資料不一致或資料丟失的問題(例如,目標資料庫中子表的資料量大於父表)。
涉及的鏈路
源庫的資料庫類型為MySQL、PolarDB for MySQL、Mariadb、PolarDB-X 1.0、PolarDB-X 2.0或OceanBase(MySQL)。
解決方案
本文為您提供手動管理刪除或更新操作和使用觸發器兩種方案,以規避該外鍵約束所引發的資料不一致問題。
樣本資料
CREATE TABLE parent (
id INT PRIMARY KEY,
name VARCHAR(50)
);
INSERT INTO parent (id, name) VALUES (1, 'Parent 1'), (2, 'Parent 2');
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 INTO child (id, parent_id, name) VALUES (1, 1, 'Child 1'), (2, 1, 'Child 2'), (3, 2, 'Child 3');
操作步驟
請先手動刪除或更新相關子表的資料,然後再刪除或更新父表的資料,以確保所有刪除或更新操作均被記錄在Binlog中。樣本如下:
DELETE FROM child WHERE parent_id = 1;
DELETE FROM parent WHERE id = 1;
UPDATE parent SET id = 3 WHERE id = 2;
UPDATE child SET parent_id = 3 WHERE parent_id = 2;
使用MySQL的觸發器,在刪除或更新父表資料時自動觸發對相應子表資料的刪除或更新操作,以確保所有刪除或更新操作均被記錄在Binlog中。樣本如下:
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 INTO parent (id, name) VALUES (3, 'Parent 3');
INSERT INTO child (id, parent_id, name) VALUES (4, 3, 'Child 4');
DELETE FROM parent WHERE id = 3;
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;
總結
通過手動管理刪除或更新操作,或者使用資料庫的觸發器,確保在DTS執行個體運行過程中,MySQL中的外鍵約束FOREIGN KEY REFERENCES ON DELETE CASCADE
或FOREIGN KEY REFERENCES ON UPDATE CASCADE
所需執行的刪除或更新操作可以被準確地記錄到Binlog中。