问题:

最近接触一个任务,多个线程需要频繁更新mysql的同一条数据,使用了脚本进行并发测试,结果发现数据结构与预期不一致。

数据表的结构类似如下:

操作数据的步骤依次是

  1. 先取出mysql中数据
  2. 应用程序中做赋值操作count = count + 1
  3. 最后update变更后的值到mysql中最近接触一个任务,需要频繁更新mysql的同一条数据,使用了脚本进行并发测试,结果发现数据结构与预期不一致。

最近整理了一些Java架构学习视频和大厂项目底层知识点,需要的同学欢迎私信我【Java】发给你~

先取出mysql中数据:

select count from table where id = #{id};

应用程序中java代码实现赋值操作count = count + 1:

int count = count + 1

最后update变更后的值到mysql中:

update table set count  = #{count} where id = #{id};

多次使用脚本开启100个线程累积1w次过后,发现总是小于1w;

分析一下,线程T1 获取到id 为1 的记录后在内存中做了count的累积,若此时另一个线程T2 也获取了id为1 的记录并且做了count = count + 1 的积累,并且更新到了mysql,此时T1再去更新id=1的记录时,就覆盖了线程T2的修改。

到此,问题已经分析出,接下来要怎么解决呢?!

mysql中的锁

  • 悲观锁
  • mysql 中select for update版本读会加悲观锁,实际上就是行锁,如果此时有并发select 或者update 、delete 操作时就会发生锁排斥,直到前面这个行锁释放过后才能继续操作,另外mysql还有个问题是select for update语句执行中所有扫描过的行都会被锁上,这一点很容易造成问题。因此如果在mysql中用悲观锁务必要确定走了索引,而不是全表扫描
  • 乐观锁
  • mysql中的乐观锁实际上是个逻辑的概念,常见的实现方式是添加个版本号version或者时间戳;每次在更新数据之前先做个compare 然后再set,即CAS 操作;回到我们的业务场景,数据表结构可以修改成如下图,每次更新前先比较version是否跟之前获取到的version一致,若一致则更新,否则失败;此时更新就类似:
update table set count  = #{count} where id = #{id} and version= #{version}; 

乐观锁和悲观锁使用场景

  • 乐观锁在不发生取锁失败的情况下开销比悲观锁小,但是一旦发生失败回滚开销则比较大,因此适合用在取锁失败概率比较小的场景,可以提升系统并发性能、
  • 悲观锁则适合频繁写入场景

来源:网易工程师-赵娟娟

看到这里的小伙伴,如果你喜欢这篇文章的话,别忘了转发、收藏、留言互动!

最近我新整理了一些Java资料,包含个人精选的Java架构学习视频、大厂实战知识点、大厂内部面试题,如果你需要的话,欢迎私信我

如果对文章有任何问题,欢迎在留言区和我交流~

并发测试mysql_实践100个线程:一次MySQL数据并发问题相关推荐

  1. 并发测试神器,模拟一次超过 5 万的并发用户

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 作者:blazemeter  |  来源:t.cn/ES7 ...

  2. 并发工具类(四)线程间的交换数据 Exchanger

    前言   JDK中为了处理线程之间的同步问题,除了提供锁机制之外,还提供了几个非常有用的并发工具类:CountDownLatch.CyclicBarrier.Semphore.Exchanger.Ph ...

  3. jmeter http并发测试设置教程(设置线程组,设置http,csv参数化,查看结果集)

    配置流程

  4. Go 学习笔记(22)— 并发(01)[进程、线程、协程、并发和并行、goroutine 启动、goroutine 特点,runtime 包函数]

    Go 语言通过编译器运行时( runtime ),从语言上支持了并发的特性. 虽然 Go 程序编译后生成的是本地可执行代码,但是这些可执行代码必须运行在Go 语言的运行时(Runtime )中.Go ...

  5. 微信支付 mysql_微信支付回调函数无法插入mysql数据

    我想在微信支付成功后通过回调插入一个订单,其中订单需要填入地址字段.如下图,其中$data['address']为地址字段,是通过获取缓存的session来得到的,但是无论直接读取session还是将 ...

  6. apache并发测试工具ab为什么测不准

    apache并发测试工具ab为什么测不准 发表于2年前(2013-03-21 12:13)   阅读(1146) | 评论(1) 1人收藏此文章, 我要收藏 赞0 3月21日 深圳 OSC 源创会正在 ...

  7. 负载测试,并发测试,压力测试区别

    负载测试 1.定义:负载测试是逐渐增加系统负载,测试系统性能的变化,最终确定系统在满足性能指标的情况下所能承受的最大负载的测试. 2.目的:在不挂系统的情况下进行测试,使系统在最大压力下正常运行. 获 ...

  8. Java并发(二十一):线程池实现原理

    一.总览 线程池类ThreadPoolExecutor的相关类需要先了解: (图片来自:https://javadoop.com/post/java-thread-pool#%E6%80%BB%E8% ...

  9. MySQL多线程并发调优

    学习MySQL数据库技术,一个非常重要的技能就是性能调优.通常情况下,都是自下而上的调优方法,主要包括运行环境.配置参数.SQL性能和系统架构设计调优等. 本文从多线程并发的角度进行的思考,简单描述M ...

最新文章

  1. uniapp防止多次点击_多次赔、不分组、价格低,守卫者3号真的这么“逆天”?...
  2. kettle分批处理大表数据_kettle-批量同步表数据
  3. 阿里内部禁用Executors创建线程池,为什么?
  4. jvm四:常量的本质含义以及助记符基本认识
  5. 【spring boot】ajax post提交遇到403
  6. 怎么把数据文件上传云服务器,怎么把数据上传导云服务器
  7. Java算法面试题:编写一个程序,将e:\neck目录下的所有.java文件复制到e:\jpg目录下,并将原来文件的扩展名从.java改为.jpg...
  8. 类型的设计--类型和成员基础(二)
  9. php文件出现UTF-8错误,php – 文件格式UTF8与BOM导致“标头已发送” – 错误
  10. 在保护继承中基类的共有成员_C++面向对象:C++ 继承
  11. QCon思考之通过Quora和Spotify案例,直击数据处理背后的魅影
  12. java 接受gsm信息_android 获取手机GSM/CDMA信号信息,并获得基站信息
  13. Android开发之科大讯飞语音合成与播报
  14. 优酷 DSP 广告投放系统架构实践
  15. Emscripten 单词_学会词根词缀,开启高效、快速地记忆英语单词模式
  16. C语言+EasyX库实现--绘制彩虹
  17. 正确判断无人机指向故障 让电子罗盘远离磁干扰
  18. 孝经白话:卿大夫章第四
  19. 接连霸榜,这门国产编程语言是真的强!
  20. Stata教程(6)---帮助功能

热门文章

  1. 用jsp实现登录界面
  2. 微服务化之缓存的设计
  3. Server 2008 配置共享文件服务器--权限配置
  4. Python 2.7:字符串乱码问题的解决
  5. 四渎《构建之法》——计划估计、敏捷流程、项目经理和用户场景
  6. C/C++通用Makefile
  7. 【python】sqlite使用
  8. 开启win7 FTP 服务 无法登陆的原因
  9. think in uml-关系
  10. ASP.NET MVC中使用FluentValidation验证实体