表 A 与表 B 结构不同,需实现:向 A 插入时同步到 B,向 B 插入时同步到 A,字段映射对应,且避免触发器循环调用。
CREATE TABLE tableA (
ID INT PRIMARY KEY,
col_A1 VARCHAR(50),
col_A2 INT,
sync_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;
CREATE TABLE tableB (
ID INT PRIMARY KEY,
col_B1 VARCHAR(50), -- 对应 col_A1
col_B2 DATE, -- 对应 col_A2 类型转换
sync_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;
DELIMITER $$
-- 表A插入触发器 -> 同步到表B
CREATE TRIGGER trg_a_after_insert
AFTER INSERT ON tableA
FOR EACH ROW
BEGIN
-- 防循环标记
IF @sync_disable IS NULL OR @sync_disable = 0 THEN
SET @sync_disable = 1;
-- 仅当B表不存在该ID时插入(避免重复)
IF NOT EXISTS (SELECT 1 FROM tableB WHERE ID = NEW.ID) THEN
INSERT INTO tableB (ID, col_B1, col_B2)
VALUES (NEW.ID, NEW.col_A1, CAST(NEW.col_A2 AS DATE));
END IF;
SET @sync_disable = 0;
END IF;
END$$
-- 表B插入触发器 -> 同步到表A
CREATE TRIGGER trg_b_after_insert
AFTER INSERT ON tableB
FOR EACH ROW
BEGIN
IF @sync_disable IS NULL OR @sync_disable = 0 THEN
SET @sync_disable = 1;
IF NOT EXISTS (SELECT 1 FROM tableA WHERE ID = NEW.ID) THEN
INSERT INTO tableA (ID, col_A1, col_A2)
VALUES (NEW.ID, NEW.col_B1, YEAR(NEW.col_B2) * 10000 + MONTH(NEW.col_B2) * 100 + DAY(NEW.col_B2));
END IF;
SET @sync_disable = 0;
END IF;
END$$
DELIMITER ;
| 技术点 | 说明 |
|---|---|
| @sync_disable 会话变量 | 同一连接内传递,防止A→B→A循环触发 |
| NOT EXISTS 检查 | 幂等保护,重复插入不报错 |
| AFTER INSERT | 主表事务提交后执行,保证数据可见性 |
| 字段映射转换 | INT↔DATE、VARCHAR长度截断等显式处理 |
-- 同步更新
CREATE TRIGGER trg_a_after_update
AFTER UPDATE ON tableA
FOR EACH ROW
BEGIN
IF @sync_disable = 0 THEN
SET @sync_disable = 1;
UPDATE tableB
SET col_B1 = NEW.col_A1, col_B2 = CAST(NEW.col_A2 AS DATE)
WHERE ID = NEW.ID;
SET @sync_disable = 0;
END IF;
END$$
-- 同步删除(慎用,建议软删除)
CREATE TRIGGER trg_a_after_delete
AFTER DELETE ON tableA
FOR EACH ROW
BEGIN
IF @sync_disable = 0 THEN
SET @sync_disable = 1;
DELETE FROM tableB WHERE ID = OLD.ID;
SET @sync_disable = 0;
END IF;
END$$