事务@transactional执行产生重复数据

news2024/11/20 11:30:25

背景

系统设计之初,每次来新请求,业务层会先查询数据库,判断是否存在相同的id数据(id是唯一标识产品的),有则返回当前数据库查到的数据,根据数据决定下一步动作,没有则认为是初次请求,将数据存入数据库,执行另一个操作。结果最近出现了并发情况下数据库产生了多条重复的数据。这里记录一下相关的思考与解决。

一. 查询数据库有哪些重复记录

方法1—使用group by 和 having子句

原理就是:将待查询列进行分组,并计算出每个分组中的行数,然后使用having子句筛选出大于1的分组返回结果。即为重复的数据列和重复次数。
举例子:查询表中重复的 sn 号列数据

select sn, count(*) as c from device_active_info group by sn having c>1;

结果:
在这里插入图片描述

方法2:使用子查询和 join 查询

方法1我只查询出了重复列字段和重复次数,那么我想查询重复的列对应的整行数据呢?
语法如下:(子查询和join表连接)

select t1.* from device_active_info t1 join (select sn, count(*) as c from device_active_info group by sn having c>1) t2 on t1.sn = t2.sn

结果就可以得到重复列的所有详细数据。

2. 为什么会产生重复记录?

按照常理来说,事务的ACID特性会保证事务的一致性。但是这里是因为:执行事务A的过程中,先查询 sn,不存在再执行插入;因为时间相对较长,事务A执行完操作尚未提交时,事务B也进来执行操作,当查询数据库中是否存在数据sn时,此时同样未查询到,因此两个事务都提交完毕后,就出现了两条sn相同的重复记录。

那么为什么会这样?加@Transactional 注解还不够吗?

不够。

3. 解决方法

方案1 给字段设置唯一索引或联合主键

这样,当插入重复数据时会发生异常,也就不会产生这个问题了。

举例子:我使用navicat给s字段添加unique唯一性约束。
在这里插入图片描述

方案2 使用synchronized 关键字且其作用域包含 proxy事务

这里注意我说的字眼,因为spring事务是基于AOP的,

1. Synchronized在事务注解@Transactional 标注的方法内或方法上

这种情况下锁是失效的。

@Transactional注解实现事务的功能是通过aop的方式实现的,在Synchronized锁生效之前就开启了事务,然后锁关闭,最后再提交事务,在高并发的情况下,存在同步锁关闭,但是事务还未提交,新的线程已经重新获取了同步锁,
数据库数据此时还未更新,新线程读到的数据是旧数据。导致Synchronized同步不生效问题
解决方法:
需要在事务开启之前开启同步锁。可以将Synchronized放置在调用事务函数之前。

在这里插入图片描述

2. Synchronized关键字同步的方法、代码块包含@Transactional事务

这种情况下是可以实现数据唯一的。

我们可以新建一个类,写一个synchronized方法然后内部调用要执行的事务方法。

public Synchronized void doTransaction(sn) {
	testService.add(sn);
}
---

@Override
@transactional
public void add(String sn) {
// 有则更新或不变;无则新增插入数据库
}

MySQL 在写入数据时,可能会出现写入两条相同记录的情况,
原因如下:
重复插入:在插入数据时,如果使用的是 INSERT INTO 语句,但没有设置主键或唯一索引,那么可能会出现重复插入相同数据的情况。这时候,MySQL 不会报错,而是直接插入数据。
多线程写入:如果有多个线程同时写入相同的数据,那么就可能会出现写入两条相同的记录的情况。这种情况下,需要使用事务来保证数据的一致性。
主从同步:在主从复制的环境下,如果主库写入了一条数据,但是还没有同步到从库,而此时主库又写入了一条相同的数据,那么就会出现写入两条相同的记录的情况。
为了避免写入两条相同的记录,可以采取以下措施:
设置主键或唯一索引,避免重复插入相同的数据。
使用事务来保证数据的一致性,避免多线程同时写入相同的数据。
在主从复制的环境下,可以采用延迟复制或者增加从库的数量来提高同步速度,避免写入两条相同的记录。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/755716.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【ArcGIS Pro二次开发】(46):要素类从上到下、从左到右排序

要素类经过编辑之后,【OBJECTID】字段会变得不规律。应部分网友要求,做了这个从上到下、从左到右排序的工具。 不过后来在ArcGIS Pro中发现了一个【排序】工具,已经可以完美实现这个功能需求,发现自己做了个白工。 不过做了不能白…

火山引擎徐广治:边缘云,下一代云计算

6月30日,2023稀土开发者大会在北京举办。大会以「代码不止,掘金不停」为主题,与上百位海内外技术专家一起剖析行业最新动态,为一直在路上的技术开发者们,拓宽技术视野,传播前沿的技术理念。火山引擎边缘云资…

图腾柱电路

驱动MOS或者IGBT管,需要比较大的驱动电流或者灌电流 使用图腾柱电路或许是一个好的办法 电流路径是这样的 当CTL1端口输出为高电平的时候 三极管Q2的2脚为高,三极管Q2不导通 三极管Q1的2脚为高,三极管导通 所以Q1的3脚和1脚导通 VCC--…

C++笔记(总)

15重载 为什么使用重载 可以让函数名相同 提高复用性 函数重载需要满足的条件 1.函数的作用域相同 2.函数的返回值相同 3.函数的参数类型不同,或者参数的个数不相同或者参数的顺序不相同或者参数的类型不相同 4.不能用函数的返回值作为判断重载判断的条件。 举个例子 根…

月薪9.8K!打破年龄瓶颈~30岁前台测试转后台优化,他说:未来可期!

海压竹枝低复举,风吹山角晦还明! 是啊,人这一辈子,该走的弯路,该吃的苦,该撞的南墙,一样都少不了,但只要我们能坚强挺住,熬过去,跨过去,好运自然来…

《Python机器学习:基于PyTorch和Scikit-Learn》——小解送书第五期

目录 书籍介绍 内容简介 作者简介 参与抽奖 书籍介绍 近年来,机器学习方法凭借其理解海量数据和自主决策的能力,已在医疗保健、 机器人、生物学、物理学、大众消费和互联网服务等行业得到了广泛的应用。自从AlexNet模型在2012年ImageNet大赛被提出以来…

【踩坑】gin框架middleware中间件如何中途跳出

gin框架middleware中间件如何中途跳出 背景 我在是使用gin web框架的时候需要自定义鉴权方式,那当然就要用到middleware这个方式了,代码如下所示,需要判断uid和token是否合法,不合法直接返回401状态,不继续往下执行 …

Android JNI引用类型管理 (十)

🔥 Android Studio 版本 🔥 🔥 JNI三种引用类型 🔥 全局引用、局部引用、弱引用 如果使用得当可以提升程序的性能, 否则会造成程序崩溃或者内存泄漏 🔥 创建包含JNI的类 JNIReference.java 🔥 package com.cmake.ndk1.jni;public class JNIReference {static {S…

什么是分布式微服务?

什么是分布式微服务? 前言什么是微服务举例说明 什么是分布式图解分布式与微服务单体架构及部署微服务架构分布式影响 分布式微服务架构什么是分布式微服务架构面临的问题 前言 本文旨在讲清楚什么是分布式微服务架构,通过解释微服务架构和分布式架构&a…

基于Java+SpringBoot+Vue的乐器社区网站设计与实现

博主介绍:✌擅长Java、微信小程序、Python、Android等,专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇🏻 不然下次找不到哟 Java项目精品实战案…

37.SpringBoot实用篇—开发(上册)

目录 一、SpringBoot实用篇—开发。 (1)热部署(开发阶段使用)。 (1.1)手动启动热部署。 (1.2)自动启动热部署。 (1.3)热部署范围配置。 (1.…

概率栅格

欢迎访问我的博客首页。 概率栅格 1. miss 表与 hit 表 1. miss 表与 hit 表 miss 表和 his 表是一维数组,它们存放的都是空闲值,用于更新概率栅格。其下标 i i i 代表旧空闲值,元素 t a b l e [ i ] table[i] table[i] 代表旧空闲值 i i …

openGauss学习笔记-10 openGauss 简单数据管理-创建表

文章目录 openGauss学习笔记-10 openGauss 简单数据管理-创建表10.1 语法格式10.2 参数说明10.3 示例 openGauss学习笔记-10 openGauss 简单数据管理-创建表 在当前数据库中创建一个新的空白表,该表由命令执行者所有。在不同的数据库中可以存放相同的表。您可以使用…

android avd

avd 记录~ avd 创建avd 默认位置安装位置.android/avd 下.android/avd/xxxx.ini 文件.android/avd/.avd 下config.ini 文件 扩展没尝试命令 avd 创建 https://developer.android.google.cn/studio/run/managing-avds?hlzh-cn https://blog.csdn.net/m0_37792384/article/det…

深入分析 workflow 线程池

深入分析 workflow 线程池 线程池是日常开发中很常用的一种管理线程的工具。它是池化技术中的一种。 池化技术的初衷就是将一些资源进行重复利用,来避免重复的构建来提高执行效率。类似的还有数据库连接池,字符串常量池,httpClient 连接池。…

git下载源码及环境搭建下载源码之后端(一)

学习目标: git下载源码 步骤: 下载源码 使用 windows R 使用cmd调用命令框下载gitee云上面的 源码文件 输入命令: Git clone (此处拼接gitee源代码 地址) 若使用 git 命令 clone 项目时 我们需要在系统变量中进行…

Ceph 存储(最详细!)

目录 一:存储基础 1、单机存储设备 (1)DAS(直接附加存储,是直接接到计算机的主板总线上去的存储) (2)NAS(网络附加存储,是通过网络附加到当前主机文件系统…

CSS 伪元素: ::marker 自定义列表序号

::marker 伪元素 ::marker&#xff0c;可作用在任何设置了 display: list-item 的元素或伪元素上&#xff0c;例如<li>和<summary>。 /** <ul><li>Peaches</li><li>Apples</li><li>Plums</li> </ul> */ ul li::…

Python教程(3)——python开发工具vscode的下载与安装

Python的开发工具有很多款&#xff0c;很多都是非常好用的&#xff0c;其中vscode作为其中一款Python的开发工具&#xff0c;是非常轻量级的&#xff0c;今天我们来介绍一下vs code的下载与安装。 vscode的下载与安装 首先需要到vscode的官网&#xff0c;这个谷歌或者百度一下…

【C++11】包装器 和 bind函数 的定义与 使用

包装器 在C11标准中&#xff0c;没有提供内置的包装器功能&#xff0c;但我们可以使用一些技术手段来实现包装器的效果。下面介绍两种常用的方法&#xff1a; 函数对象包装器 函数对象包装器&#xff08;Function Object Wrapper&#xff09;&#xff1a; C11引入了 std::fu…