MySQL中REPLACE未生成重复数据的原因排查(含自增主键与MUL索引)
问题解析:为什么REPLACE执行两次却只生成一条数据?
嘿,我来帮你把这个问题捋清楚!核心原因其实是你表上的**联合唯一索引n_d(包含name和date)**在起作用,再加上REPLACE语句的特殊逻辑,才导致了和预期不一样的结果。
先搞懂REPLACE的工作逻辑
REPLACE和普通的INSERT最大的区别是:它会先检查表中的所有唯一键(包括主键、唯一索引),如果发现有冲突的行(即唯一键值完全匹配),就会先删除那行冲突的数据,再插入新的行。而不是像你以为的那样,因为没指定自增主键id,就直接插入新行。
结合你的场景一步步看
你的脚本把同一条REPLACE语句执行了两次,我们来拆解每一步的操作:
- 第一次执行:
表是空的,没有任何匹配name='Joe'且date='2018-01-05'的行(联合唯一索引n_d也没有冲突),所以直接插入一条新数据,自增主键id自动生成(比如是1)。 - 第二次执行:
MySQL检查到n_d联合唯一索引已经存在('Joe', '2018-01-05')的匹配行,触发了REPLACE的替换逻辑:- 先删掉之前那条
id=1的记录 - 再插入一条新的记录,此时自增主键会变成2(因为自增计数器不会因为删除操作回滚)
- 先删掉之前那条
所以最终你的表中只会剩下最后一次插入的那条记录,看起来就像只执行了一次一样。
关于MUL索引的误解纠正
你之前误解了MUL索引的含义:MUL只是表示该列是某个非唯一索引的一部分,但这里的n_d是联合唯一索引(从show index结果可以确认),它的优先级和主键一样,会触发REPLACE的冲突检查逻辑。这和普通的非唯一MUL索引完全不同。
怎么得到预期的两条重复数据?
如果你确实想要生成两条主键不同、但name/date/size都相同的记录,有几种办法:
- 改用
INSERT语句代替REPLACE(前提是你的业务允许name+date重复,或者先去掉n_d联合唯一索引) - 让两次执行的
REPLACE语句中,name或date有一个不一样(避开联合唯一索引的冲突)
内容的提问来源于stack exchange,提问作者Brick
相关产品推荐
相关产品推荐

