Mysql之事务(并发)初体验
来源:互联网 发布:手机淘宝退货流程图 编辑:程序博客网 时间:2024/06/05 14:01
先声明本人菜鸟,不喜勿喷。
模拟应用场景是,支付下单,减少库存。
我建了三个表,goods、orders、logs 都是用的InnoDB引擎,不然不支持事务
goods里面的字段,id,name,price,stock(库存)
orders里面有 id,uid,ordersn,good_id,createtime
logs 里面有 id,status,uid
以上表的id都是自增长的主键
用的tp3.2测试的
插入一条数据到goods
public function addgoods(){ $data = array( 'name' => '小米手机', 'price' => 100, 'stock' => 10 ); M('goods')->add($data); }
然后就是弄一个创建订单的方法createOrder,同时更新了库存,在弄一个call调用
简单的写了下这个下单的过程,可以理解为,就一个insert一个update 不带事务
public function call(){ $this->createOrder(1, 1); } public function createOrder($uid,$goodid){ $good = M('goods')->find(1); if(!$good['stock'] > 0) { return false; } $data = array( 'ordersn' => NOW_TIME.rand(1000000,9999999), 'good_id' => $goodid, 'createtime' => NOW_TIME, 'uid' => $uid ); $orderid = M('orders')->add($data); $stock = $good['stock'] - 1; $goodupdate = M('goods')->where('stock > 0 and id = 1' )->save(array('stock' => $stock)); if($orderid && $goodupdate){ $status = '成功'; }else{ $status = '失败'; } return M('logs')->add(array('uid' =>$uid,'status' => $status)); }
然后下载了一个叫ab的所谓web性能测试工具
我们就调用call方法 100次试试。
发现库存确实是0了(减少了10个),但是orders表里面有47条数据。我滴个龟龟。。好吓人
如果说这是一个秒杀,100个人同时去买,有47个订单是成功的。但是库存却只有10个。
如果并发更高呢?后果不堪设想。。
我们加添加事务试试。。
public function createOrder($uid,$goodid){ M()->startTrans(); $good = M('goods')->find(1); if(!$good['stock'] > 0) { return false; } $data = array( 'ordersn' => NOW_TIME.rand(1000000,9999999), 'good_id' => $goodid, 'createtime' => NOW_TIME, 'uid' => $uid ); $orderid = M('orders')->add($data); $stock = $good['stock'] -1; $goodupdate = M('goods')->where('stock > 0 and id = 1' )->save(array('stock' => $stock)); if($orderid && $goodupdate){ $status = '成功'; M()->commit(); }else{ $status = '失败'; M()->rollback(); } return M('logs')->add(array('uid' =>$uid,'status' => $status)); }
加了这几句, 其他代码也没变
M()->startTrans(); M()->commit(); M()->rollback();
库存还原到10个,清空logs和orders,再跑一边看结果吧。
库存依然正常到0了,但是orders有28条数据,啥情况。。。是不是事务写错了,还是tp里面的事务有bug?这不是闹眼子吗。。
然后我特意去测试tp的事务,写一个update然后回滚,看行不行。。结果是可以的。。
那么我这个代码到底哪里出了问题。。写了事务咋还不行?
原来忘记了一个大问题,那就是没锁表。。。
我们把
$good = M('goods')->find(1);
修改为
$good = M('goods')->lock(true)->find(1); // lock相当于是加了个for update 我们用的InnoDB支持行级锁
再试试。。
库存正常为0,orders和logs都只有10条数据了。应该就正常了。。
我们在试试1000个并发,依然是稳稳的10条数据。。
如果只是小量的并发,用事务和锁表完全可以解决。
- Mysql之事务(并发)初体验
- MySQL之锁、事务、并发控制
- MySQL之初体验
- Mysql事务、事务并发及、事务隔离
- 并发之事务隔离
- LINQ体验(10)——LINQ to SQL语句之开放式并发控制和事务
- LINQ体验(10)——LINQ to SQL语句之开放式并发控制和事务
- LINQ体验(10)——LINQ to SQL语句之开放式并发控制和事务
- LINQ体验(10)——LINQ to SQL语句之开放式并发控制和事务
- LINQ体验(10)--LINQ to SQL语句之开放式并发控制和事务
- LINQ体验(10)--LINQ to SQL语句之开放式并发控制和事务
- LINQ体验(10)——LINQ to SQL语句之开放式并发控制和事务
- LINQ体验(10)——LINQ to SQL语句之开放式并发控制和事务
- LINQ体验(10)——LINQ to SQL语句之开放式并发控制和事务
- mysql之初体验二
- mysql 复制之初体验
- MYSQL EVENT 之初体验
- MySQL复制之初体验
- spark job, stage, task介绍
- STM32堆栈整理
- 如何在Ubuntu中查找自己安装的软件包
- Python学习笔记(4)——Python Lists and Dictionaries
- poj3185 The Water Bowls 开关问题
- Mysql之事务(并发)初体验
- ThinkCmf目录结构
- [leetcode122].为何此时贪心解是最优解 ?
- Numpy.Zeros等
- 宽高自适应
- [hibernate]Turn your Session into FlushMode.COMMIT/AUTO,请教这种配置怎么处理
- 抓包神器Charles使用
- 【SVN技巧】如何协同开发LabVIEW代码
- macOS开发中客户端和javaScript的互调(使用Swift开发)