insert ignore能跳过重复数据是因为它仅对primary key或unique索引冲突静默降级为警告,不报错、不插入、不更新;前提必须是表已建对应唯一约束,否则行为同普通insert。

INSERT IGNORE 为什么能跳过重复数据
INSERT IGNORE 的核心机制是:当插入时遇到违反唯一约束(PRIMARY KEY 或 UNIQUE 索引)的记录,MySQL 不报错,而是静默忽略这一行。它不是“去重后再插”,而是“插失败就跳过”。所以前提必须是表里已有对应索引——没有 UNIQUE 或主键,INSERT IGNORE 和普通 INSERT 行为完全一样。
常见错误现象:ERROR 1062 (23000): Duplicate entry 'xxx' for key 'PRIMARY' 依然出现 → 检查是否漏建唯一索引;或误以为它能根据某列“自动去重”,结果重复数据照常插入(因无约束)。
怎么写 INSERT IGNORE 才真正生效
语法和普通 INSERT 一致,只多一个 IGNORE 关键字:
INSERT IGNORE INTO users (id, name, email) VALUES (1, 'Alice', 'a@example.com');
关键实操点:
- 必须确保目标字段(如
email)上有UNIQUE索引,例如:ALTER TABLE users ADD UNIQUE (email); - 如果用复合唯一索引(如
UNIQUE (name, email)),只有两列值同时重复才会被忽略 - 不建议在没有明确业务唯一性定义的表上硬加
UNIQUE索引来凑合用INSERT IGNORE,容易掩盖数据模型问题 -
INSERT IGNORE对非唯一键冲突(如外键约束失败、字段类型超长)仍会报错,它只捕获重复键错误
INSERT IGNORE 和 REPLACE INTO、ON DUPLICATE KEY UPDATE 有什么区别
三者都处理重复场景,但行为完全不同:
-
INSERT IGNORE:冲突则跳过,原记录不动,新数据丢弃,返回影响行数为0 -
REPLACE INTO:冲突则先删后插,自增 ID 可能变化,触发器会被执行两次(DELETE + INSERT),有性能和数据一致性风险 -
ON DUPLICATE KEY UPDATE:冲突时可指定更新字段,比如INSERT INTO t SET id=1, count=1 ON DUPLICATE KEY UPDATE count = count + 1;,更灵活可控
性能上,INSERT IGNORE 开销最小(无删除/更新逻辑),但能力也最弱——它不能补全、不能累加、不能标记状态。
批量插入时 INSERT IGNORE 的实际表现
对 INSERT IGNORE ... VALUES (...), (...), (...) 这类多值语句,MySQL 是逐行判断的:某一行冲突就跳过,其余行照常插入。不会因为其中一行失败导致整条语句回滚。
需要注意的坑:
- 返回的
affected rows是实际插入的行数,不是总尝试数,无法直接得知“跳过了几行” - 如果想统计跳过数量,得配合
SELECT预查(如先查SELECT COUNT(*) FROM t WHERE email IN ('a@b', 'c@d')),或者改用ON DUPLICATE KEY UPDATE并设一个计数器字段 - 在事务中使用时,
INSERT IGNORE的跳过不产生锁等待,但依然会持有插入意向锁(Insert Intention Lock),高并发下可能引发间隙锁竞争
真正要靠它“安全灌数据”,索引设计、批量粒度、以及是否接受静默丢弃,这三点缺一不可。











