您好,登录后才能下订单哦!
本篇文章给大家分享的是有关Mysql事务并发然后就解决,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。
在开发中遇到过这样一个问题
一个看视频记录,更新到100就表示看完了,后面再有请求不继续更新了.
结果是:
导致,里面很多数据出现问题.
推测是以下的情况才会导致
第一条请求 事务在执行中,还未提交(因为本地有时候比较难再现,于是手动在程序中,第一条记录处理的时候,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;
会发现成功不了,一直处于等待状态.
查看锁
确实被锁住了,这里只要执行第一个事务的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进行多线程测试,从最开始的多条记录更新成功,变成只有一个成功,后面的失败.
从最开始的插入多条记录,到后来的只能插入一条数据了
以上就是Mysql事务并发然后就解决,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。