SQL表的数据镜像同步是指当源表发生数据变更时,目标表自动同步对应的变更内容,配置AFTER INSERT和UPDATE双向触发器是实现该需求的高效方案,无需引入额外的同步工具,仅依赖数据库自身的触发器机制即可完成。

双向触发器同步的核心逻辑
双向同步需要为两个参与同步的表分别创建触发器,避免单向同步导致的数据循环触发问题。核心规则如下:
- 表A插入数据时,触发表B插入相同数据
- 表A更新数据时,触发表B更新对应记录
- 表B插入数据时,触发表A插入相同数据
- 表B更新数据时,触发表A更新对应记录
为了避免触发器无限循环执行,需要在触发器内部增加判断逻辑,当数据已经同步过时不再次触发同步操作,通常可以通过增加同步标识字段或者判断当前操作是否由触发器发起来实现。
准备工作:创建测试表
首先创建两个结构相同的测试表,作为镜像同步的源表和目标表,这里以MySQL数据库为例:
-- 创建表A
CREATE TABLE table_a (
id INT PRIMARY KEY AUTO_INCREMENT,
user_name VARCHAR(50) NOT NULL,
user_age INT,
sync_flag TINYINT DEFAULT 0 COMMENT '同步标识,1表示由触发器同步生成,避免循环触发'
);
-- 创建表B,结构与表A完全一致
CREATE TABLE table_b (
id INT PRIMARY KEY AUTO_INCREMENT,
user_name VARCHAR(50) NOT NULL,
user_age INT,
sync_flag TINYINT DEFAULT 0 COMMENT '同步标识,1表示由触发器同步生成,避免循环触发'
);
为表A配置AFTER INSERT/UPDATE触发器
表A的触发器负责在表A发生插入或更新操作时,同步数据到表B,同时设置sync_flag为1,标记该记录是触发器同步产生的。
表A的AFTER INSERT触发器
DELIMITER //
CREATE TRIGGER trg_table_a_after_insert
AFTER INSERT ON table_a
FOR EACH ROW
BEGIN
-- 只有当插入的记录不是触发器同步产生时才同步到表B
IF NEW.sync_flag = 0 THEN
INSERT INTO table_b (id, user_name, user_age, sync_flag)
VALUES (NEW.id, NEW.user_name, NEW.user_age, 1);
END IF;
END //
DELIMITER ;
表A的AFTER UPDATE触发器
DELIMITER //
CREATE TRIGGER trg_table_a_after_update
AFTER UPDATE ON table_a
FOR EACH ROW
BEGIN
-- 只有当更新的记录不是触发器同步产生时才同步到表B
IF NEW.sync_flag = 0 THEN
UPDATE table_b
SET user_name = NEW.user_name,
user_age = NEW.user_age,
sync_flag = 1
WHERE id = NEW.id;
END IF;
END //
DELIMITER ;
为表B配置AFTER INSERT/UPDATE触发器
表B的触发器逻辑与表A完全一致,负责在表B发生插入或更新操作时,同步数据到表A,同样设置sync_flag为1避免循环触发。
表B的AFTER INSERT触发器
DELIMITER //
CREATE TRIGGER trg_table_b_after_insert
AFTER INSERT ON table_b
FOR EACH ROW
BEGIN
-- 只有当插入的记录不是触发器同步产生时才同步到表A
IF NEW.sync_flag = 0 THEN
INSERT INTO table_a (id, user_name, user_age, sync_flag)
VALUES (NEW.id, NEW.user_name, NEW.user_age, 1);
END IF;
END //
DELIMITER ;
表B的AFTER UPDATE触发器
DELIMITER //
CREATE TRIGGER trg_table_b_after_update
AFTER UPDATE ON table_b
FOR EACH ROW
BEGIN
-- 只有当更新的记录不是触发器同步产生时才同步到表A
IF NEW.sync_flag = 0 THEN
UPDATE table_a
SET user_name = NEW.user_name,
user_age = NEW.user_age,
sync_flag = 1
WHERE id = NEW.id;
END IF;
END //
DELIMITER ;
功能验证
我们可以通过插入和更新操作验证双向同步是否生效:
测试插入同步
-- 向表A插入数据,sync_flag默认是0
INSERT INTO table_a (user_name, user_age) VALUES ('张三', 25);
-- 查询两个表的数据,表B应该同步到相同记录
SELECT * FROM table_a;
SELECT * FROM table_b;
执行后可以看到表A和表B都有一条id为1,姓名为张三,年龄25的记录,且表B的sync_flag为1。
测试更新同步
-- 更新表B的用户年龄 UPDATE table_b SET user_age = 26 WHERE id = 1; -- 查询两个表的数据,表A的年龄应该同步更新为26 SELECT * FROM table_a; SELECT * FROM table_b;
执行后可以看到表A和表B的user_age都变为26,且表A的sync_flag为1。
注意事项
- 不同数据库的触发器语法存在差异,上述示例为MySQL语法,SQL Server、Oracle等数据库需要调整触发器的创建语法和变量引用方式
- 如果同步的表结构不一致,需要调整触发器中插入和更新的字段列表,保证对应字段的类型和含义匹配
- 触发器的执行会增加数据操作的耗时,如果表的数据变更非常频繁,需要评估性能影响,必要时可以优化同步逻辑或者采用其他同步方案
- 删除操作的同步可以根据需求补充AFTER DELETE触发器,逻辑与插入更新类似,在源表删除时同步删除目标表对应记录
SQL触发器数据镜像同步AFTER_INSERT触发器AFTER_UPDATE触发器双向同步修改时间:2026-07-24 09:12:28