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进行多线程测试,从最开始的多条记录更新成功,变成只有一个成功,后面的失败.

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 深入mysql并发插入优化详解

    使用storm处理日志的时候,经常会遇到并发插入mysql的效率问题,到网上查了些资料,做一下笔记将表的引擎改为 myisam, 修改 my.cnf 的concurrent_insert=2,concurrent_insert 可以设的值有 0 1 2 ,2 是完全支持并发插入 1) concurrent _insert =0 ,无论MyISAM的表数据文件中间是否存在因为删除而留下俄空闲空间,都不允许concurrent insert. 2)concurrent_insert = 1,是当My

  • PHP+MySQL高并发加锁事务处理问题解决方法

    本文实例讲述了PHP+MySQL高并发加锁事务处理问题解决方法.分享给大家供大家参考,具体如下: 1.背景: 现在有这样的需求,插入数据时,判断test表有无username为'mraz'的数据,无则插入,有则提示"已插入",目的就是想只插入一条username为'mraz'的记录. 2.一般程序逻辑如下: $conn = mysqli_connect('127.0.0.1', 'root', '111111') or die(mysqli_error()); mysqli_selec

  • MySQL中SELECT+UPDATE处理并发更新问题解决方案分享

    问题背景: 假设MySQL数据库有一张会员表vip_member(InnoDB表),结构如下:   当一个会员想续买会员(只能续买1个月.3个月或6个月)时,必须满足以下业务要求: •如果end_at早于当前时间,则设置start_at为当前时间,end_at为当前时间加上续买的月数 •如果end_at等于或晚于当前时间,则设置end_at=end_at+续买的月数 •续买后active_status必须为1(即被激活) 问题分析: 对于上面这种情况,我们一般会先SELECT查出这条记录,然后根

  • 分析MySQL并发下的问题及解决方法

    1.背景 对于数据库系统来说在多用户并发条件下提高并发性的同时又要保证数据的一致性一直是数据库系统追求的目标,既要满足大量并发访问的需求又必须保证在此条件下数据的安全,为了满足这一目标大多数数据库通过锁和事务机制来实现,MySQL数据库也不例外.尽管如此我们仍然会在业务开发过程中遇到各种各样的疑难问题,本文将以案例的方式演示常见的并发问题并分析解决思路. 2.表锁导致的慢查询的问题 首先我们看一个简单案例,根据ID查询一条用户信息: mysql> select * from user where

  • MySQL并发更新数据时的处理方法

    UPDATE是否会加锁? SQL语句为如下时,是否会加锁? UPDATE table1 SET num = num + 1 WHERE id=1; 答案是不会 实际上MySQL是支持给数据行加锁(InnoDB)的,并且在UPDATE/DELETE等操作时确实会自动加上排它锁.只是并非只要有UPDATE关键字就会全程加锁,针对上面的MySQL语句而言,其实并不只是一条UPDATE语句,而应该类似于两条SQL语句(伪代码): a = SELECT * FROM table1 WHERE id=1;

  • Tomcat+Mysql高并发配置优化讲解

    1.Tomcat优化配置 (1)更改Tomcat的catalina.bat 将java变成server模式,增大jvm的内存,在文件开始位置增加 setJAVA_OPTS=-server -Xms1024m -Xmx2048m -Xss512K -XX:PermSize=128m-XX:MaxPermSize=256m setCATALINA_OPTS=-server -Xms512m -Xmx512m 如下图: Xms:初始内存 Xmx:最大内存 (2)更改Tomcat的Server.xml

  • 利用mysql事务特性实现并发安全的自增ID示例

    项目中经常会用到自增id,比如uid,最简单的方法就是用直接用数据库提供的AUTO_INCREMENT,但是如果用户量非常大,几千万,几亿然后需要分表存储的时候呢,这种方案就搞不定了,所以最好有一个全局的自增ID的生成器,不管是否分表,都能从生成器中获取到全局自增的ID. 实现方法应该有很多,不过所有的方案都需要解决一个问题,就是保证在高并发的情景下,数据获取依然正确,每次获取的ID都不会重复. 这里我分享两种利用mysql的innodb的事务特性来实现的方案,一种是实现过了的,另一种没有试验过

  • MySQL中实现高性能高并发计数器方案(例如文章点击数)

    现在有很多的项目,对计数器的实现甚是随意,比如在实现网站文章点击数的时候,是这么设计数据表的,如:"article_id, article_name, article_content, article_author, article_view--在article_view中记录该文章的浏览量.诈一看似乎没有问题.对于小站,比如本博客,就是这么做的,因为小菜的博客难道会涉及并发问题吗?答案显而易见,一天没多少IP,而且以后不会很大. 言归正传,对文章资讯类为主的项目,在浏览一个页面的时候不但要进行

  • PHP利用Mysql锁解决高并发的方法

    前面写过利用文件锁来处理高并发的问题的,现在我们说另外一个处理方式,利用Mysql的锁来解决高并发的问题 先看没有利用事务的时候并发的后果 创建库存管理表 CREATE TABLE `storage` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `number` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=l

  • Yii+MYSQL锁表防止并发情况下重复数据的方法

    本文实例讲述了Yii+MYSQL锁表防止并发情况下重复数据的方法.分享给大家供大家参考,具体如下: lock table 读锁定 如果一个线程获得在一个表上的read锁,那么该线程和所有其他线程只能从表中读数据,不能进行任何写操作. lock tables user read;//读锁定表 unlock tables;//解锁 lock tables user read local;//本地读锁定表,其他线程的insert未被阻塞,update操作被阻塞 lock table 写锁定 如果一个线

随机推荐