IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> 解决数据重复插入的sql与锁方案 -> 正文阅读

[大数据]解决数据重复插入的sql与锁方案

解决数据重复插入的sql与锁方案

一、问题

在实际应用中,用户可能会有连点操作,当连点操作的时间间隔非常短时,系统很容易造成重复数据的插入,如图所示:

在这里插入图片描述

可以看到有2条数据被重复插入了(encrytedPassword一致),尽管userId是不同的。

二、解决方案

1.从sql方面解决,这里可以根据数据库表是否有其他唯一索引来划分:

a.表中除了主键外,还有唯一索引时:

假设表中除了主键,存在某一字段a是唯一索引,且已存在于表中的数据为1

  • 使用ignore关键字 如果是用主键primary或者唯一索引unique区分了记录的唯一性,避免重复插入记录可以使用:
INSERT IGNORE into user(a,b,c) VALUES('1','joshua317','13299999999');

插入a=1冲突,这样当有重复记录就会忽略,执行后返回数字0

  • 使用Replace
REPLACE into user(a,b,c) VALUES('1','joshua317','13299999999');

REPLACE的运行与INSERT很相像,但是如果旧记录与新记录有相同的值,则在新记录被插入之前,旧记录被删除

  • 使用ON DUPLICATE KEY UPDATE
INSERT INTO `table` (`a`, `b`, `c`) VALUES (1, 2, 3) ON DUPLICATE KEY UPDATE `c`=`c`+1; 

加入a是唯一索引时,如果表中已存在a=1,则插入失败,等价于下面的update语句

UPDATE `table` SET `c`=`c`+1 WHERE `a`=1;

b.表中不存在唯一索引时

上面规定a为表中的唯一索引,但很多时候表中除了id外,是不存在唯一索引的,我们又不能随便改变公司的表结构,所以可以使用下面的方案:

  • 先查询后插入,伪代码:
@Transactional
User register(User user){
	User user = UserDao.SelectUserByUid(user.getUid());
	if(null==user){
		user = UserDao.save(user);
	}
	return user;
}

这种方法并发时可能会出现错误,比如用户第一次点击时,执行register方法,当前的user查询为null,还没执行save方法时,用户再次点击时,并发执行了register方法,并且完成后,线程回到第一次操作中,再次执行save方法,会导致user重复插入。所以我们要加上**@Transactional**保证事务的原子性。另外这种方法性能稍微差一些

  • **使用insert ignore if not exist,**具体格式为:
INSERT IGNORE INTO 表名('字段') 
 SELECT '字段需要插入时的数据' FROM dual 
WHERE NOT EXISTS
 (SELECT * FROM '表名' WHERE '需要被限制不重复的字段' = '被限制字段本次插入的数据')

比如mybatis使用时为:

INSERT IGNORE INTO user(a,b,c) 
 SELECT #{a},#{b},#{c} FROM dual 
WHERE NOT EXISTS
 (SELECT a,b,c FROM user WHERE b = #{b})

解释一下:

第一行的insert ignore我们知道,插入不进去就取消插入操作

第二行的dual是虚表,select 1,2,3 是合法的,但为了好看,所以变成select xxx from dual虚表

第三行和第四行顾名思义,如果存在b的某个值以及在数据库中存在,那么第一行的insert不生效。

参考:

https://blog.csdn.net/qq_23490959/article/details/90669128

https://blog.csdn.net/b644ROfP20z37485O35M/article/details/108633274

https://www.csdn.net/tags/NtzaggysMDMzNDEtYmxvZwO0O0OO0O0O.html

三、悲观锁(分布式锁)方案:

上面虽然是不错的解决方案,但是如果一个工程中所有的save代码都已经写好了,那么都得全部都按照上面的方法改一遍吗?太麻烦了,比如:

在这里插入图片描述

另外,如果是分布式呢?一个save方法在多个服务中都存在时,上面的方法 很多时候是不适用的。

所以我们应该从根源解决问题,百因必有果,重复插入操作的根源就是重复执行了这段代码,那我们完全可以使用锁的方式把这段代码锁住,防止重复性操作。

待续解释分布式锁。。。。

参考

https://juejin.cn/post/6904629373383639048

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-06-25 18:11:43  更:2022-06-25 18:11:51 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 21:51:42-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码