建议使用以下浏览器,以获得最佳体验。 IE 9.0+以上版本 Chrome 31+ 谷歌浏览器 Firefox 30+ 火狐浏览器
请选择 进入手机版 | 继续访问电脑版
设置昵称

在此一键设置昵称,即可参与社区互动!

确定
我再想想
选择版块
标签
您还可以添加5个标签
  • 没有搜索到和“关键字”相关的标签
  • 云产品
  • 解决方案
  • 技术领域
  • 通用技术
  • 平台功能
取消

小果果

发帖: 61粉丝: 1

级别 : 外部版主

发消息 + 关注

发表于2020年09月22日 23:05:22 260 1
直达本楼层的链接
楼主
显示全部楼层
[技术分享] Mysql事务并发问题解决方案

在开发中遇到过这样一个问题

一个看视频记录,更新到100就表示看完了,后面再有请求不继续更新了.

结果是:

                       image.png

导致,里面很多数据出现问题.

推测是以下的情况才会导致.

第一条请求 事务在执行中,还未提交(因为本地有时候比较难再现,于是手动在程序中,

第一条记录处理的时候,sleep了几秒,就达到这种效果了)

第二条请求 事务已经开始执行,这个时候查到的历史最大值不是100,才会去进行了更新

网上看了一下解决方案:

悲观锁

直接锁行记录

这个我在本地测试,确实有效,一个事务开始没结束,第二个事务一个等待,

不过会导致处于阻塞状态,因为系统并发,不敢考虑,也就是记录下这个方式.

手动模拟:

执行第一个事务:

-- 视频100BEGIN;
 
SELECT * FROM `biz_coursestudyhistory` WHERE sid = 5777166;
 
UPDATE biz_coursestudyhistory set studyStatus = 100,versionNO=versionNO+1 WHERE sid = 1 AND versionNO = 0;
 
-- commit ; 先不执行,先注解掉,只执行上面的

接着执行第二个事务:

BEGIN;
  
UPDATE biz_coursestudyhistory set studyStatus = 90,versionNO=versionNO+1 WHERE sid = 1 AND versionNO = 0;
  
SELECT * FROM `biz_coursestudyhistory` WHERE sid = 1 FOR UPDATE;
  
COMMIT;

会发现成功不了,一直处于等待状态.

查看锁

                     image.png

确实被锁住了,这里只要执行第一个事务的commit ,第二个事务就会执行.

从这里可以看出,行锁可以直接达到理想的数据统一状态,一个事务修改,其他都不能操作,感觉这种比较适合银行这种安

全性的项目

乐观锁:

这种比较简单,并且不会造成阻塞

方式就是加上版本号

var maxver = select max(version) from table

更新的话使用

update table set studystatus = xxx,version = version +1 where id =1 and version = maxver

写入的话

INSERT into table (contentStudyID,courseWareID,studyStatus,studyTime,endTime)
SELECT 27047358,3163,100,333,NOW() FROM dual WHERE NOT EXISTS (SELECT 1 FROM table WHERE contentStudyID =27047358 AND
courseWareID = 3163
 )

这种方式,可以在更新或者写入的时候,直接判断库里面存在的数据是否存在,如果不存在则是别其他的线程使用了.

修改为这种写法后,使用jmeter进行多线程测试,从最开始的多条记录更新成功,变成只有一个成功,后面的失败.

从最开始的插入多条记录,到后来的只能插入一条数据了

                               image.png

举报
分享

分享文章到朋友圈

分享文章到微博

运气男孩

发帖: 107粉丝: 16

级别 : 外部版主

发消息 + 关注

发表于2020年09月30日 23:59:59
直达本楼层的链接
沙发
显示全部楼层

点赞 评论 引用 举报

游客

富文本
Markdown
您需要登录后才可以回帖 登录 | 立即注册