在开发中遇到过这样一个问题
一个看视频记录,更新到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,事务,并发问题,解决
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
RTX 5090要首发 性能要翻倍!三星展示GDDR7显存
三星在GTC上展示了专为下一代游戏GPU设计的GDDR7内存。
首次推出的GDDR7内存模块密度为16GB,每个模块容量为2GB。其速度预设为32 Gbps(PAM3),但也可以降至28 Gbps,以提高产量和初始阶段的整体性能和成本效益。
据三星表示,GDDR7内存的能效将提高20%,同时工作电压仅为1.1V,低于标准的1.2V。通过采用更新的封装材料和优化的电路设计,使得在高速运行时的发热量降低,GDDR7的热阻比GDDR6降低了70%。