thinkphp6使用mysql悲观锁解决商品超卖问题的实现_第1页
thinkphp6使用mysql悲观锁解决商品超卖问题的实现_第2页
thinkphp6使用mysql悲观锁解决商品超卖问题的实现_第3页
thinkphp6使用mysql悲观锁解决商品超卖问题的实现_第4页
thinkphp6使用mysql悲观锁解决商品超卖问题的实现_第5页
已阅读5页,还剩1页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第thinkphp6使用mysql悲观锁解决商品超卖问题的实现悲观锁介绍(百科):

悲观锁,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度,因此,在整个数据处理过程中,将数据处于锁定状态。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)。

使用场景举例:以MySQLInnoDB为例

商品goods表,假设商品的id为1,购买数量为1,status为1表示上架中,2表示下架。现在用户购买此商品,在不是高并发的情况下处理逻辑是:

查找此商品的信息;

检查商品库存是否大于购买数量;

修改商品库存和销量;

上面这种场景在高并发访问的情况下很可能会出现问题。如果商品库存是100个,高并发的情况下可能会有1000个同时访问,在到达第2步的时候,都会检测通过。这样会出现商品库存是-900个的情况。显然着不满足需求!!!

商品表结构:

CREATETABLE`goods`(

`id`int(11)unsignedNOTNULLAUTO_INCREMENT,

`name`varchar(100)COLLATEutf8_unicode_ciNOTNULLDEFAULT'',

`status`tinyint(1)NOTNULLDEFAULT'1',

`total`int(11)NOTNULLDEFAULT'0',

`sell`int(11)NOTNULLDEFAULT'100',

`price`decimal(10,2)NOTNULL,

PRIMARYKEY(`id`)

)ENGINE=InnoDBAUTO_INCREMENT=1DEFAULTCHARSET=utf8COLLATE=utf8_unicode_ci;

INSERTINTO`test`.`goods`(`id`,`name`,`status`,`total`,`sell`,`price`)VALUES(1,'商品',1,0,100,15.00);

订单表结构:

CREATETABLE`orders`(

`id`int(11)unsignedNOTNULLAUTO_INCREMENT,

`uid`int(11)NOTNULLDEFAULT'0',

`create_time`datetimeNOTNULL,

`status`tinyint(1)NOTNULLDEFAULT'1',

`goods_id`int(11)NOTNULLDEFAULT'0',

`order_no`varchar(200)COLLATEutf8_unicode_ciNOTNULLDEFAULT'',

PRIMARYKEY(`id`)

)ENGINE=InnoDBAUTO_INCREMENT=1DEFAULTCHARSET=utf8COLLATE=utf8_unicode_ci;

使用悲观锁处理。

当我们在查询出goods信息后就把当前的数据锁定,直到我们修改完毕后再解锁。那么在这个过程中,因为goods被锁定了,就不会出现有第三者来对其进行修改了。

注:要使用悲观锁,我们必须关闭mysql数据库的自动提交属性,因为MySQL默认使用autocommit模式,也就是说,当你执行一个更新操作后,MySQL会立刻将结果进行提交。thinkphp6中使用事务,手动进行提交回滚。

namespaceapp\controller;

useapp\BaseController;

usethink\facade\Db;

classTestextendsBaseController

*不加锁

*@returnstring|void

publicfunctiontest_1()

$num=1;

$goods_id=1;

Db::startTrans();

try{

$where=[];

$where['id']=$goods_id;

$where['status']=1;

$goods_info=Db::table('goods')-where($where)-find();

if(empty($goods_info)){

return'商品不存在';

$total=$goods_info['total'];

$sell=$goods_info['sell'];

if($total$num){

return'库存不足';

$data['total']=$total-$num;

$data['sell']=$sell+$num;

$res=Db::table('goods')-where(['id'=$goods_id])-update($data);

$order_data=[];

$order_data['uid']=rand(1000,9999);

$order_data['status']=1;

$order_data['create_time']=date('Y-m-dH:i:s');

$order_data['goods_id']=$goods_id;

$order_data['order_no']=date('YmdHis').rand(1000,10000);

$order_res=Db::table('orders')-insert($order_data);

Db::commit();

}catch(\Exception$e){

//回滚事务

Db::rollback();

echo$e-getMessage();

exit('rollback');

echo'请求成功';

*加锁--悲观锁

*@returnstring|void

publicfunctiontest_2()

$num=1;

$goods_id=1;

Db::startTrans();

try{

$where=[];

$where['id']=$goods_id;

$where['status']=1;

$goods_info=Db::table('goods')-lock(true)-where($where)-find();

if(empty($goods_info)){

return'商品不存在';

$total=$goods_info['total'];

$sell=$goods_info['sell'];

if($total$num){

return'库存不足';

$data['total']=$total-$num;

$data['sell']=$sell+$num;

$res=Db::table('goods')-where(['id'=$goods_id])-update($data);

$order_data=[];

$order_data['uid']=rand(1000,9999);

$order_data['status']=1;

$order_data['goods_id']=$goods_id;

$order_data['order_no']=date('YmdHis').rand(1000,10000);

$order_data['create_time']=date('Y-m-dH:i:s');

$order_res=Db::table('orders')-insert($order_data);

Db::commit();

}catch(\Exception$e){

//回滚事务

Db::rollback();

echo$e-getMessage();

exit('rollback');

echo'请求成功';

}

使用jmeter工具测试,创建线程测试组:

关于使用jmeter创建测试高并发例子,可查看:使用JMeter进行高并发测试_左右..的博客-

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论