前段时间我踩过一个坑:在mysql8的一张innodb引擎的表中,加了唯一索引,但最后发现数据竟然还是重复了。
到底怎么回事呢?
本文通过一次踩坑经历,聊聊唯一索引,一些有意思的知识点。
1.还原问题现场前段时间,为了防止商品组产生重复的数据,我专门加了一张防重表。
如果大家对防重表,比较感兴趣,可以看看我的另一篇文章 《高并发下如何防重?》,里面有详细的介绍。
问题就出在商品组的防重表上。
具体表结构如下:
CREATE TABLE `product_group_unique` (
`id` bigint NOT NULL,
`category_id` bigint NOT NULL,
`unit_id` bigint NOT NULL,
`model_hash` varchar(255) COLLATE utf8mb4_bin DEFAULT NULL,
`in_date` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
为了保证数据的唯一性,我给那种商品组防重表,建了唯一索引:
alter table product_group_unique add unique index
ux_category_unit_model(category_id,unit_id,model_hash);
根据分类编号、单位编号和商品组属性的hash值,可以唯一确定一个商品组。
给商品组防重表创建了唯一索引之后,第二天查看数据,发现该表中竟然产生了重复的数据:
表中第二条数据和第三条数据重复了。
这是为什么呢?
2.唯一索引字段包含null如果你仔细查看表中的数据,会发现其中一个比较特殊地方:商品组属性的hash值(model_hash字段)可能为null,即商品组允许不配置任何属性。
在product_group_unique表中插入了一条model_hash字段等于100的重复数据:
执行结果: