• 欢迎来到本博客,希望可以y一起学习与分享

并发手动处理数据唯一(不依靠唯一索引)

MySQL benz 3周前 (05-01) 15次浏览 0个评论 扫描二维码
文章目录[隐藏]

场景

有两张表,gift礼品表、record记录表:

使用代码向gift表添加不重复的礼包码:

检查gift表,礼包码是否有重复:

业务逻辑

1、从gift表取出一个未被领取的礼包,更新领取人;
2、把领取的礼包码以及领取人、领取时间插入record记录表;

要求:
1、record表的礼包码必须唯一;
2、record表和gift表,同一个礼包码的领取人必须一致;

分析

1、由于gift表需要update、record表需要insert,这需要用到事务。
2、record的礼包码需要唯一,可以在cdk这个字段加一个唯一索引,这是一个方法,但是不在这次讨论范围。从上面的record表结构来看,cdk字段并没有加唯一索引,所以,需要手动处理cdk礼包码唯一的问题;还有一种场景是项目已上线,才发现record表的cdk礼包码字段没有加唯一索引,而且已产生重复的礼包码数据,在不改动已有数据的情况下,这时候再加唯一索引会报错,加不了,只能手动处理cdk礼包码字段数据唯一的问题,确保后面的数据正确。

核心

要解决以上问题,需要通过这段sql来解决:

以record表为例:

解析sql语句

第一步: select * from record where cdk='626e13edd8481',根据需要唯一的字段,查询表里的数据;
第二步:select '626e13edd8481','jack',1651378403 from dual where not exists (...),如果不存在数据【where not exists】,select的数据【select ‘626e13edd8481′,’jack’,1651378403】当作values插入表中;如果存在数据,则不操作(影响行数为0)。

虚拟表 dual

参考: MySQL-DUAL


不知道涉及哪个表的时候,可以指定DUAL作为一个假的表名。
DUAL单纯为了方便声明了SELECT,需要使用FROM或者其他子句的时候。MySQL可能忽略这些子句。如果没有指定表,MySQL不需要FROM DUAL。

select '626e13edd8481','jack',1651378403 from dual where not exists (select * from record where cdk='626e13edd8481');为例,原本是想通过判断表中是否存在数据来返回select的数据作为插入数据的,即:
select '626e13edd8481','jack',1651378403 where not exists (select * from record where cdk='626e13edd8481');

但是根据sql的语法格式,是select...from 表名 where ...,还差一个表名,所以这个需要一个虚拟表dual,作为 from dual成为合法的sql语句。

测试

开两个窗口模拟两个用户在操作

检查record表的礼包码有没有重复


文章 并发手动处理数据唯一(不依靠唯一索引) 转载需要注明出处
喜欢 (0)

您必须 登录 才能发表评论!