jsp做网站注册页面,wordpress强大之处,我国的跨境电商平台有哪些,杭州的网站建设公司哪家好谈到了MySQL悲观锁#xff0c;但是悲观锁并不是适用于任何场景#xff0c;它也有它存在的一些不足#xff0c;因为 悲观锁大多数情况下依靠数据库的锁机制实现 #xff0c;以保证操作最大程度的独占性。 如果加锁的时间过长#xff0c;其他用户长时间无法访问#xff0c;…谈到了MySQL悲观锁但是悲观锁并不是适用于任何场景它也有它存在的一些不足因为 悲观锁大多数情况下依靠数据库的锁机制实现 以保证操作最大程度的独占性。 如果加锁的时间过长其他用户长时间无法访问影响了程序的并发访问性同时这样对数据库性能开销影响也很大 特别是对长事务而言这样的开销往往无法承受。所以与悲观锁相对的我们有了乐观锁具体参见下面介绍 乐观锁介绍
乐观锁 Optimistic Locking 相对悲观锁而言 乐观锁假设认为数据一般情况下不会造成冲突 所以在数据进行提交更新的时候才会正式对数据的冲突与否进行检测如果发现冲突了则让返回用户错误的信息让用户决定如何去做。那么我们如何实现乐观锁呢一般来说有以下2种方式
1.使用数据版本Version记录机制实现这是乐观锁最常用的一种实现方式。何谓数据版本即为数据增加一个版本标识一般是通过为数据库表增加一个数字类型的 “version” 字段来实现。当读取数据时将version字段的值一同读出数据每更新一次对此version值加一。当我们提交更新的时候判断数据库表对应记录的当前版本信息与第一次取出来的version值进行比对如果数据库表当前版本号与第一次取出来的version值相等则予以更新否则认为是过期数据。用下面的一张图来说明
如上图所示如果更新操作顺序执行则数据的版本version依次递增不会产生冲突。但是如果发生有不同的业务操作对同一版本的数据进行修改那么先提交的操作图中B会把数据version更新为2当A在B之后提交更新时发现数据的version已经被修改了那么A的更新操作会失败。 2.乐观锁定的第二种实现方式和第一种差不多同样是在需要乐观锁控制的table中增加一个字段名称无所谓字段类型使用时间戳timestamp, 和上面的version类似也是在更新提交的时候检查当前数据库中数据的时间戳和自己更新前取到的时间戳进行对比如果一致则OK否则就是版本冲突。 使用举例 以MySQL InnoDB为例
还是拿之前的实例来举商品goods表中有一个字段statusstatus为1代表商品未被下单status为2代表商品已经被下单那么我们对某个商品下单时必须确保该商品status为1。假设商品的id为1。 下单操作包括3步骤
1.查询出商品信息
select (status,status, version ) from t_goods where id#{id}
2.根据商品信息生成订单
3.修改商品status为2
update t_goods
set status2, versionversion1
where id#{id} and version#{version} ; 那么为了使用乐观锁我们首先修改t_goods表增加一个version字段数据默认version值为1。
t_goods表初始数据如下
Sql代码
mysql select * from t_goods; --------------------------- | id | status | name | version | --------------------------- | 1 | 1 | 道具 | 1 | | 2 | 2 | 装备 | 2 | --------------------------- 2 rows in set mysql
对于乐观锁的实现我使用MyBatis来进行实践具体如下
Goods实体类
Java代码
/** * ClassName: Goods * Function: 商品实体. * date: 2013-5-8 上午09:16:19 * author chenzhou1025126.com */ public class Goods implements Serializable { /** * serialVersionUID:序列化ID. */ private static final long serialVersionUID 6803791908148880587L; /** * id:主键id. */ private int id; /** * status:商品状态1未下单、2已下单. */ private int status; /** * name:商品名称. */ private String name; /** * version:商品数据版本号. */ private int version; Override public String toString(){ return good id:id,goods status:status,goods name:name,goods version:version; } //setter and getter }
GoodsDao
Java代码
/** * updateGoodsUseCAS:使用CAS(Compare and set)更新商品信息. * * author chenzhou1025126.com * param goods 商品对象 * return 影响的行数 */ int updateGoodsUseCAS(Goods goods);
mapper.xml
Xml代码 idupdateGoodsUseCAS parameterTypeGoods update t_goods set status#{status},name#{name},versionversion1 where id#{id} and version#{version} ]]
GoodsDaoTest测试类
Java代码
Test public void goodsDaoTest(){ int goodsId 1; //根据相同的id查询出商品信息赋给2个对象 Goods goods1 this.goodsDao.getGoodsById(goodsId); Goods goods2 this.goodsDao.getGoodsById(goodsId); //打印当前商品信息 System.out.println(goods1); System.out.println(goods2); //更新商品信息1 goods1.setStatus(2);//修改status为2 int updateResult1 this.goodsDao.updateGoodsUseCAS(goods1); System.out.println(修改商品信息1(updateResult11?成功:失败)); //更新商品信息2 goods1.setStatus(2);//修改status为2 int updateResult2 this.goodsDao.updateGoodsUseCAS(goods1); System.out.println(修改商品信息2(updateResult21?成功:失败)); }
输出结果
Shell代码
good id:1,goods status:1,goods name:道具,goods version:1 good id:1,goods status:1,goods name:道具,goods version:1 修改商品信息1成功 修改商品信息2失败
说明
在GoodsDaoTest测试方法中我们同时查出同一个版本的数据赋给不同的goods对象然后先修改good1对象然后执行更新操作执行成功。然后我们修改goods2执行更新操作时提示操作失败。此时t_goods表中数据如下
Sql代码
mysql select * from t_goods; --------------------------- | id | status | name | version | --------------------------- | 1 | 2 | 道具 | 2 | | 2 | 2 | 装备 | 2 | --------------------------- 2 rows in set mysql
我们可以看到 id为1的数据version已经在第一次更新时修改为2了。所以我们更新good2时update where条件已经不匹配了所以更新不会成功具体sql如下
Sql代码
update t_goods set status2,versionversion1 where id#{id} and version#{version};
这样我们就实现了乐观锁 以上就是我对MySQL乐观锁的总结和实践写得比较浅显有不对的地方欢迎拍砖
以上也是我工作当中经常用到的一种方式。