mysql悲观锁与乐观锁的实现方案,mysql悲观锁与乐观锁的实现方案一样吗,MySQL悲观锁与乐观锁的实现方案

mysql悲观锁与乐观锁的实现方案,mysql悲观锁与乐观锁的实现方案一样吗,MySQL悲观锁与乐观锁的实现方案

我们知道Mysql并发事务会造成更新丢失,解决方法是锁,所以本文将分析锁(乐观锁,悲观锁)。本文主要介绍MySQL悲观锁和乐观锁方案的相关信息,有需要的可以参考一下。

目录

前言实战

1.没有锁2。悲观锁3。乐观锁定概述

前言

悲观锁和乐观锁是用来解决并发问题的两种思想,在不同的平台上有各自的实现。比如在Java中,synchronized可以看作是悲观锁的实现(不严谨,有一个锁升级的过程,只有升级到重量级锁的时候),Atomic*** atomic class可以看作是乐观锁的实现。

悲观锁

具有很强的独占性和排他性特征,数据在整个处理过程中被锁定,一般通过系统的互斥来实现。当其他线程想要获取锁时,它们将被阻塞,直到持有锁的线程释放它。

乐观锁

对数据修改和访问保持乐观,假设不会有冲突。只有在提交数据进行更新时,才会检测到数据冲突。如果没有冲突,更新将被成功提交,否则,它将很快失败,并返回一个错误给用户选择下一步做什么。通常,失败后,用户将继续重试,直到成功提交更新。

MySQL本身支持锁定机制。比如我们有一个“写前检查”的要求。我们希望整个过程是原子操作,中间不能中断。此时可以通过在被查询的数据线上添加“独占锁”来实现。只要当前事务不释放锁,MySQL就会阻塞其他事务的独占锁,直到当前事务释放锁。MySQL底层的这种独占锁被称为“悲观锁”。

MySQL本身不提供乐观锁的功能,需要开发者自己实现。通常的做法是在表中添加一个版本列来标记数据行的版本。当我们需要更新数据时,我们必须比较版本。版本一致表示该数据在此期间未被其他事务修改,否则表示该数据被其他事务修改,我们需要自旋重试。

真正的战斗

假设数据库有两个表:商品表和订单表。

用户下单后需要执行两个操作:

货物减去库存表。

表来创建记录。

初始数据:ID为1的商品有100个库存,订单表数据为空。

客户端启动10个线程和订单。在无锁、悲观锁、乐观锁场景下有哪些表现?

下面是创建表的sql语句:

-商品清单

创建表“商品”(

` id ' bigint(20)NOT NULL AUTO _ INCREMENT,

` goods _ name ' varchar(50)不为空,

` price '小数(10,2)不为空,

` stock` int(11)默认值' 0 ',

` version` int(10) unsigned NOT NULL默认为' 0 ',

主键(` id `)

)ENGINE=InnoDB AUTO_INCREMENT=1默认字符集=utf8

-订单

创建表` t_order `(

` id ' bigint(20)NOT NULL AUTO _ INCREMENT,

` goods _ id ' bigint(20)不为空,

` order_time` datetime不为空,

使用BTREE的主键(` id `)

)ENGINE=InnoDB AUTO_INCREMENT=1默认字符集=utf8

1、无锁

没有任何治疗。

//下订单

私有布尔顺序(){

goods goods=goods mapper . selectbyid(1L);

布尔成功=假;

if (goods.getStock() 0) {

goods . set stock(goods . getstock()-1);

//更新库存

goodsMapper.updateById(商品);

//创建订单

order mapper . save(goods . getid());

成功=真;

}

返回成功;

}

控制台输出结果:

2、悲观锁

查询商品时,添加FOR UPDATE,给数据行添加独占锁,这样再次查询时其他线程会被阻塞。在当前线程的事务提交并释放锁之前,其他线程可以继续下单。这种方法的并发性能不高。

Sql语句

@ Select(' Select * FROM goods WHERE id=# { id } FOR UPDATE ')

商品选择更新(长id);

控制台输出结果:

注意:FOR UPDATE必须在一个事务中有效,并且查询和更新必须在同一个事务中!

3、乐观锁

实现思路是:每次更新都检查版本号。如果版本号一致,当前线程可以正常提交更新;否则数据已经被其他线程修改,当前线程需要自旋重试,直到业务成功。

更新数据时,版本号必须自己增加!

@ Update(' Update goods SET stock=# { stock },version=version 1,其中id=#{id}和version=#{version} ')

int updateByVersion(长id,整数股票,整数版本);

商业代码

布尔顺序(){

goods goods=goods mapper . selectbyid(1L);

布尔成功=假;

if (goods.getStock() 0) {

goods . set stock(goods . getstock()-1);

//用版本号更新清单。

int result=goods mapper . updatebyversion(goods . getid()、goods.getStock()、goods . getversion());

if(结果=0) {

//更新失败,说明期间数据已经被其他线程修改,需要递归重试。

退货单();

}

//创建订单

order mapper . save(goods . getid());

成功=真;

}

返回成功;

}

控制台输出结果:

总结

关于MySQL悲观锁和乐观锁方案的这篇文章到此为止。有关MySQL悲观锁和乐观锁的更多信息,请搜索我们以前的文章或继续浏览下面的相关文章。希望你以后能支持我们!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • 使用php连接mysql数据库,php连接数据库的方法
  • 使用php连接mysql数据库,php连接数据库的方法,一文详解PHP连接MySQL数据库的三种方式
  • pymysql菜鸟教程,pymysql 使用
  • pymysql菜鸟教程,pymysql 使用,pymysql模块使用简介与示例
  • mysql锁实现,mysql锁算法
  • mysql锁实现,mysql锁算法,MySQL锁机制与用法分析
  • mysql连接报错10061,mysql连接错误10060
  • mysql连接报错10061,mysql连接错误10060,MYSQL无法连接 提示10055错误的解决方法
  • mysql连接报10060错误,mysql连接报错10055
  • mysql连接报10060错误,mysql连接报错10055,MySQL连接异常报10061错误问题解决
  • mysql辅助索引和主键索引,mysql 主键 外键 索引
  • mysql辅助索引和主键索引,mysql 主键 外键 索引,MySQL索引之主键索引
  • MySQL语句大全,mysql常见语句总结
  • MySQL语句大全,mysql常见语句总结,MySQL语句整理及汇总介绍
  • mysql触发器的使用方法实验报告,mysql中触发器的使用
  • 留言与评论(共有 条评论)
       
    验证码: