1.悲观锁

是指在数据处理中,使数据处于锁定状态。

1.1 实现

1.1.1 mysql设置

使用悲观锁,必须关闭mysql的自动提交,set autocommit = 0 ,mysql默认使用自动提交模式。

1.1.2 sql语句

  1. #1:查出商品数量
  2. select quantity from goods where id = 100 for update;
  3. #2:根据商品信息生成订单
  4. insert into orders(id,goods_id) values(null,100);
  5. #3:修改商品的库存
  6. update goods set quantity = quantity-1 where id = 100;

select...for update是mysql提供的实现悲观锁的方式。

2.乐观锁

乐观锁相对悲观锁而言,它认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测。

2.1 实现

2.1.1 版本号

利用数据版本号机制是乐观锁最常用的一种实现方式。一般通过为数据库表增加一个数字类型的“version”字段,当读取数据时,将version字段的值一同读出,数据每更新一次,version值+1。当我们提交更新的时候,判断数据表对应的当前版本信息与第一次取出来的version值是否一致,一致则更新,否则更新失败。

  1. #1:查询商品数量和version
  2. select (quantity,version) from goods where id = 100;
  3. #2:根据商品信息生成订单
  4. insert into orders (id,goods_id) values(null,100);
  5. #3:修改商品的库存
  6. update goods set quantity = quantity -1,version = version +1 where id = 100 and version = #上面查询的version

2.1.2 秒杀系统的思路

  1. <?php
  2. $res = DB::update('update goods set quantity = quantity - 1 where id = ? and quantity -1 >= 0', [1]);
  3. if ($res) {
  4. DB::insert('insert into orders (goods_id,price) values (?,?)', [1,4999]);
  5. DB::insert('insert into logs (content,create_at) values (?,?)', ['抢购成功',date('Y-m-d H:i:s')]);
  6. }else{
  7. DB::insert('insert into logs (content,create_at) values (?,?)', ['抢购失败',date('Y-m-d H:i:s')]);
  8. }