问题描述:在之前的应用开发中,有这么一个需求,多个用户会对阅读内容提出自己的意见,后端采用不记名方式,前者提的意见会覆盖后者的意见。 系统在运行过程中出现过一个问题,二个用户都对同一篇文章提意见,时间相同,前端在用户的二个客户端浏览器下分别获取到数据库中都不存在这条记录,所以当用户同时点击保存的时候数据库中会有针对这篇文章的两条数据,这与实际业务规定的不符合。

针对这个问题可能出现的原因咱们来分析一下原因:
(1)最不靠谱的情况是,A用户发现数据库没有数据,编辑完后产生一条,同时B用户也发现从来没有用户编辑过这条数据,从而也产生一条数据,此时前端已经存在二条相关数据了,后端没有任何判断和校验,直溜溜的插入库里,这种一般程序员应该不会犯;
(2)在(1)一样的前提下,产生二条相关数据,程序员在service中先查一个数据是否存在,如果不存在相关数据就插入,存在则更新原有记录,这种会很大程度的解决重复数据的问题。但是应付不了多并发的情况,大家都知道Mysql支持可重复读模式,当第一个线程已经插入但是还没有提交的时候,另一个事务在执行期间是读不到这个数据的,还是会执行插入,谁也不能保证他们不是同时commit的,这样数据库中又出现了两条数据,此时问题无法解决;
(3)有的程序员暴脾气,没招就只能把这个任务交给数据库拜,给数据库表加唯一索引,看它还插入,当然,这种不管不顾的做法确实保证了最终的数据没问题,但是这是以牺牲程序的可用性为前提的,没有经验的程序员还有可能把这个错误留给前端,客户都能看到异常,更有可能导致参与的事务不回滚,造成其他数据问题。无论怎么样一句话就是本次用户白干了拜而且还发现系统出问题了,暴脾气的用户一个电话就找过来了,这样很不好啊!

最终解决方案
synchronized 参数从来都是为控制并发设计的,当然这个是以牺牲性能为前提的,一个系统你得先保证数据对的前提下,你才能去保证性能吧。有的同学直接随意的在service的方法上加入这个synchronized 参数,这太随意了,其实他没注意到自己的方法上加了@Transactional参数开启了事务,大家都知道事务是通过AOP动态代理实现的,执行这个方法之前,先打开数据库连接,开启事务,当进入这个方法的时候,锁才开始起作用,当这个方法退出,事务还是没有结束,还没有commit提交的情况下,另一个事务执行的进度就赶上了了,又可以同时提交,最终出现2条数据,那问题出现在哪呢?
问题是你这个synchronized 应该加到调用这个service的地方,让锁能够控制整个事务提交过程,这样就能保证数据的唯一性了,所以有些事情如果程序能够解决的不要交给数据库处理,如果哪天来个新手整错脚本,漏掉了这个校验,还是会有脏数据入库,你只能苦哈哈的在一片声讨声中处理历史数据,怎一个惨字了得!!!
如果大家有别的更好更优雅的办法也请不吝赐教。

如何保证数据库表中数据的唯一性相关推荐

  1. mysql数据库--表中数据的基本操作

    约束: 1.主键(primary key) : 它的整个列中元素唯一且非空. auto_increment 自动增加 每次加1,只能用于创建表时.报错.删除数据也会自增. 需要 truncate ta ...

  2. Oracle数据库----表中数据的操作(插入、更新、删除数据)

    文章目录 一.插入数据 插入多行数据的简单方法: 1.将表一的全部数据添加到表二中 创建副本Courses1,只复制Courses的结构 将Courses表中的数据拷贝到Courses1中 创建副本的 ...

  3. MySQL~数据库表中数据的增删查改(基础篇)

    文章目录 增加 建表 多行数据 全列插入 多行数据 指定列插入 查询 全列查询 指定列查询 查询字段为表达式 查询字段 名字重定义 去重 distinct 排序 order by 条件查询 运算符 比 ...

  4. mysql 查询表 第一列报错_MySQL----DQL(查询数据库表中数据)

    ##DQL:查询表中的记录 1.语法: select 字段列名 from 表名列表 where 条件列表 group  by 分组字段 having  分组之后的条件 order  by 排序 lim ...

  5. 将数据库表中数据转为XML

    SQL语句如下: View Code 1 CREATE TABLE #CUSTOMER( 2 ID INT NOT NULL, 3 NAME VARCHAR(30), 4 TELE VARCHAR(9 ...

  6. 怎么删除mysql表中数据_如何删除数据库表中的数据?

    删除数据库表中数据有两种方式: 第一种:delete from tablename where 1=1; 第二种:truncate  table tablename; 区别是:第二种清空表数据比较及时 ...

  7. 【唠叨两句】如何将一张树型结构的Excel表格中的数据导入到多张数据库表中...

    小弟昨天遇到一个相对比较棘手的问题,就像标题说的那样.如何将一张树型结构的Excel表格中的数据导入到多张数据库表中,在现实中实际是七张数据库表,这七张表之间有着有着相对比较复杂的主外键关系,对于我这 ...

  8. app把信息添加到mysql_如何将数据库表中的数据添加到ListView C#Xamarin Android App

    几天前我问过如何在活动之间共享数据,一个用户告诉我使用SQLite,所以我做了.我想让用户点击MainLayout中的按钮,它会将他重定向到AddTaskLayout,在那里他可以添加任务名称,按下S ...

  9. 如何创建最简单的 ABAP 数据库表,以及编码从数据库表中读取数据 (上) 试读版

    ABAP 标准培训教程 BC400 学习笔记之一:ABAP 服务器的架构和一个典型的 ABAP 程序结构介绍 ABAP 标准培训教程 BC400 学习笔记之二:Cross-client 和 Clien ...

最新文章

  1. C++ 从双重检查锁定问题 到 内存屏障的一些思考
  2. 网络推广软件浅谈关键词如何布置才能让优化更事半功倍!
  3. 企业项目开发--切分配置文件
  4. 【最新】2020年4月学术会议变动汇总
  5. 用JS实现发邮件的功能 完美解决
  6. 杭电2035--人见人爱A^B
  7. Linux深入学习专业书
  8. stcc52单片机时钟电路_单片机与晶振到底有什么关系?
  9. 基于Vue2.0+Vuex+Axios+NodeJs+Express+MySQL实现京东移动web商城
  10. qqkey获取原理_QQ key盗号木马原理分析
  11. COGS 2507 零食店
  12. wpf 复制到粘贴板_将WPF UI单元复制到剪贴板-阿里云开发者社区
  13. 邮件服务器的安全,邮件服务器的安全解决方案
  14. ubuntu11.04(unix 就可以了) 共享文件以及支持上传文件
  15. NumPy 数组属性
  16. 没有U盘怎么给电视盒子装软件?新手必看三种方法
  17. android代码判断当前手机的手机号码是属于移动、联通、还是电信的
  18. 证明厄米矩阵不同特征值对应特征向量正交
  19. java写渗透工具_常用渗透测试工具使用tips
  20. linux主机 asp主机 java主机 区别,计算机中支持asp的主机是什么操作系统

热门文章

  1. 9月刊上市:绩效考核的五种死因(推荐文章)
  2. php 屏蔽 strict standards,PHP 5禁用嚴格的標准錯誤
  3. 【三维CAD设计经验分享】CrownCAD设计:导航入门
  4. 【AGC】通过AGC认证服务在Android平台实现华为账号登录功能
  5. 基于AT89C51的电子时钟系统
  6. android玩游戏怎么换绑,QQ炫舞手游该帐号已在安卓平台使用 请切换至安卓平台登录该账号或更换大区...
  7. git rebase合并多次commi
  8. Python中的面向对象编程(类编程)由简单到复杂的示例代码
  9. mui中去掉li的下划线
  10. python求解一元一次方程