跨数据库表数据同步遇主键冲突,求每5分钟迁移的解决方案
解决跨库表同步的主键冲突与定时迁移问题
先纠正一下你原来SQL里的小问题:你要把db2.table的数据同步到db1.table,所以插入目标应该是db1.table,之前的语句方向搞反啦。下面分两部分帮你解决问题:
一、主键冲突的两种处理方案
首先得明确你的业务需求:是用db2的行完全覆盖db1的同主键行,还是只更新对应字段?两种场景的SQL写法不同:
1. 主键重复时整行覆盖(推荐如果db2是权威数据源)
用INSERT ... ON DUPLICATE KEY UPDATE语法,当主键field_id重复时,直接用db2的字段值替换db1的对应行:
USE db1; INSERT INTO table (field_id, field1, field2) SELECT field_id, field1, field2 FROM db2.table ON DUPLICATE KEY UPDATE field1 = VALUES(field1), field2 = VALUES(field2); -- 注:主键field_id不用更新,因为已经是重复值,写上也不影响
2. 主键重复时仅更新指定字段
如果db1里有些字段是本地维护的,不想被db2覆盖,就只同步需要更新的字段(比如只更field1和field2),写法和上面类似,只是明确指定更新的字段即可。
关键前提:
db1.table和db2.table的field_id必须是主键或者唯一索引,否则ON DUPLICATE KEY UPDATE不会触发,还是会报主键冲突错误。
二、每5分钟自动迁移的实现方案
存储过程是可选方案,不是必须的,这里给你两种常用的实现方式:
1. 用MySQL事件调度器+存储过程
先把同步逻辑封装成存储过程,再用事件调度器定时调用:
-- 创建存储过程 DELIMITER // CREATE PROCEDURE SyncDb2ToDb1() BEGIN USE db1; INSERT INTO table (field_id, field1, field2) SELECT field_id, field1, field2 FROM db2.table ON DUPLICATE KEY UPDATE field1 = VALUES(field1), field2 = VALUES(field2); END // DELIMITER ; -- 启用MySQL事件调度器(默认可能关闭) SET GLOBAL event_scheduler = ON; -- 创建每5分钟执行一次的事件 CREATE EVENT SyncTablesEvery5Min ON SCHEDULE EVERY 5 MINUTE STARTS CURRENT_TIMESTAMP DO CALL SyncDb2ToDb1();
2. 直接用系统定时任务(无需存储过程)
如果不想用MySQL的事件,也可以直接用系统的定时任务来执行SQL脚本:
- Linux/macOS:编辑crontab,添加定时任务(注意替换用户名、密码和SQL):
*/5 * * * * mysql -u your_username -p'your_password' -e "USE db1; INSERT INTO table (field_id, field1, field2) SELECT field_id, field1, field2 FROM db2.table ON DUPLICATE KEY UPDATE field1=VALUES(field1), field2=VALUES(field2);"
安全提示:不要明文写密码,最好用
~/.my.cnf配置文件存储账号密码,避免泄露。
- Windows:用「任务计划程序」创建定时任务,执行
mysql.exe并传入SQL命令。
额外优化建议
如果你的表数据量很大,每次同步全表会影响性能,可以考虑添加时间过滤条件(如果表有更新时间字段的话),比如只同步最近5分钟新增/修改的数据:
SELECT field_id, field1, field2 FROM db2.table WHERE update_time >= DATE_SUB(NOW(), INTERVAL 5 MINUTE)
这样能大幅减少每次同步的数据量,提升效率。
内容的提问来源于stack exchange,提问作者warfy




