前段时间,我踩过一个洞:在一枚发动机里,加了,但最后居然还是发现了。
到底怎么了。
在此期间,为了不让商品群发生重复数据,专门追加了一张。
如果大家对称重感兴趣,可以看看我的另一篇文章。
详细介绍了“在高并发下如何防止重量”。
问题在于商品群的重量计。
具体的表结构包括:。
为了保证数据,我建立了这样一个商品群防重表,唯一的索引:
您可以根据分类编号、单位编号和商品组属性的散列值唯一确定一个商品组。
制作商品组的反计量器后,第二天确认了数据,发现表中出现了重复数据:
表中的第二个数据和第三个数据重复。
为什么呢。
仔细查看表中的数据,商品组属性的hash值可能允许商品组不设置属性。
执行结果:
从上图可以看出,mysql的唯一性约束已生效,重复数据已被阻止。
从图中可以看出,竟然执行成功了。
换句话说,如果在唯一索引字段中显示空值,则不启用唯一约束。
最终插入的数据情况如下:。
model _如果hash字段不是空的,则不会生成重复的数据。
model _如果hash字段为空,则生成重复数据。
创建唯一索引的字段不能为空。否则,可能会禁用mysql的唯一性约束。
众所周知,独特的索引非常简单、易于使用,但有时很难添加到表中。
别信,我们一起往下看。
通常,要删除表中的记录,请使用语句。
例如:
删除此记录后,sql语句几乎不会检测到此delete操作。
另一种是主要由语句操作。
例如:
逻辑删除需要在表中添加删除状态字段,以记录数据是否已删除。所有业务查询的位置都必须过滤删除的数据。
这样删除数据后,数据就在表中,只是对删除状态的数据进行了逻辑过滤。
实际上,这种逻辑删除的表不能有唯一的索引。
为什么呢。
假设之前对商品表的和进行了唯一的索引,用户删除了记录,则delete_status设置为1。后来,该用户发现错了,又重新添加了同样的商品。
由于唯一的索引存在,该用户无法第二次添加商品,即使该商品被删除,也无法添加。
这个问题显然有点严重。
也许有人会说:“那么,和三个场地同时做不就好了吗 ”。
A:如果删除具有用户逻辑的商品,然后重新添加相同的商品,则可以可靠地解决无法添加的问题。但是,第二次追加的商品,又被删除了。这个用户第三次添加同样的商品,是不是也会出现问题。
这意味着如果表具有逻辑删除功能,则不方便创建唯一索引。
但是,如果希望在包含逻辑删除的表中添加唯一的索引,该怎么办呢。
如前所述,如果表具有逻辑删除功能,则不方便创建唯一索引。
其根本原因是在删除记录之后,delete_status设置为1,默认值为0。当第二次删除同一记录时,delete_status设置为1,但由于创建了唯一索引同时将name、model和delete_status这三个字段设置为唯一索引,因此数据库具有delete_因为status是1的记录,所以这次操作失败。
我们为什么不改变主意:delete_status为1,delete_status为1、2、3等,大于1表示删除。
然后,每次删除时都会获取该相同记录的最大删除状态,并将其加1。
这样,数据操作过程如下所示。
记录a、delete_status=0。
记录a、delete_status=1。
记录a、delete_status=0。
记录a、delete_status=2。
记录a、delete_status=0。
记录a、delete_status=3。
由于记录a,每次删除时delete_所有status都是不同的,因此可以确保唯一性。
该方案的优点是不需要调整字段,非常简单和直接。
缺点是:可能需要修改sql逻辑,特别是一些查询sql语句,一些delete_在确定status=1删除状态的情况下,delete_status>=1。
从逻辑上删除表,不容易添加唯一索引的最根本位置是从逻辑上删除表。
我们为什么不添加字段,而专门处理逻辑删除功能呐。
A:可以增加字段。
然后,如果有逻辑删除操作,则会自动将时间戳写入该字段。
这会在同一记录中多次执行逻辑删除,每次生成时都会有不同的时间戳,从而确保数据的唯一性。
时间戳通常是准确的。
对同一记录执行两次不同的逻辑删除操作,生成相同的时间戳。
可以精确指定时间戳。
该方案的优点是可以通过添加新字段来实现数据的唯一性,而无需更改现有代码逻辑。
缺点是,在极限情况下,可能会出现重复数据。
实际上,增加时间戳字段可以解决问题。但是,在极限情况下,可能会出现重复数据。
你有解决这个问题的办法吗。
A:添加字段:delete_id。
该方案的思想是在添加数据时delete_id设置默认值1,逻辑删除时delete_id被代入当前记录的主键id。
name,model,delete _status和delete_id,同时使四个字段成为唯一的索引。
这可能是一个最佳方案,不需要修改现有的删除逻辑,也可以保证数据的唯一性。
如前所述,如果表具有逻辑删除功能,那么建立唯一索引并不太好,但是通过本文介绍的三种方案,您可以顺利地建立唯一索引。
但是,来自灵魂的问题:如果某个表已经存在,该如何索引呢。
最简单的方法是增加一张来初始化数据。
可以写这样的sql:
这是可能的,但今天的主题是直接在原始表中添加唯一的索引,而不使用重复表。
那么,如何添加这个独特的索引呢。
实际上,您可以参考在上一节中添加字段的想法。
delete _id字段。
要获取同一记录的最大标识:
然后delete_id字段设置为1。
下一步,在其他相同记录的delete_选择id字段,然后选择当前主字段 中所述修改相应参数的值。
这样就可以区分历史的重复数据了。
所有delete_如果在id字段中设置值,则name、model和delete_status和delete_id,在四个字段中添加了唯一的索引。
完美。
接下来,我们来谈谈如何在大字段中添加独特的索引。
有时,name、model、delete_status和delete_id等。
但是,如果model字段较大,则创建此唯一索引并占用更多存储空间。
我们都知道唯一的索引,也可以走索引。
在索引的每个节点上保存大数据会大大降低检索效率。
因此,必须限制唯一的索引长度。
目前,mysql innodb存储引擎中的索引允许最大长度为3072bytes,其中unqiue key最大长度为1000bytes。
如果字段太大且超过1000bytes,则无法添加唯一索引。
这个时候有解决办法吗。
可以增加hash字段,取较大字段的hash值,生成较短的新值。该值可以由固定长度16比特或32比特等的一些hash算法生成。
name、hash、delete _status和delete_使用id字段添加唯一索引。
这可以避免唯一索引过长的问题。
但它也会带来新的问题。
典型的hash算法生成两个不同值的hash冲突,hash算法生成相同的值。
当然,您也可以区分其他字段,例如name,允许业务上的重复数据,并且不将其写入数据库。
如果添加唯一索引真的很难,请使用其他技术手段确保唯一性,而不添加唯一索引。
如果新数据的条目很少,例如只需job,或者只需导入数据,就可以按照一个线程的顺序执行。这确保表中的数据不会重复。
如果新数据条目较多,最终将发送mq消息,在mq消费者中以单线程处理。
因为字段太大,所以在mysql中很难建立独特的索引,为什么不使用呢。
但是,name、model、delete_status和delete_id字段,加号,显然没有意义,效率也不高。
与5.1章结合,name、model、delete_status和delete_使用id字段生成散列值并锁定新值。
遇到hash冲突也没关系。同时发生的情况下,说到底是小概率活动。
一些年轻人可能认为,既然有redis分布式锁,就不用使用唯一的索引。
那是你没有遇到的,大量插入数据的场景。
执行查询操作后,必须找到列表中的数据并将其批量插入数据库。
使用redis分布式锁时,需要执行以下操作:。
在一个循环中,必须锁定每个数据。
这样性能肯定不会变好。
当然,一些同伴反对使用redis的一揽子操作是否可以。
也就是说,一次上锁500或1000个数据,最后一次释放这些锁
想想都有点不靠谱,这把钥匙有多大呐。
由于锁定容易超时,例如未运行业务代码,因此锁定已过期。
对于这样的批量操作,此时如果使用mysql的唯一索引,则只要将直接insert汇总,则一个sql语句即可。
数据库自动确定,如果有重复数据,则报告错误。如果不存在重复数据,则允许插入数据。
发表评论