前言
笔者之前在面试京东的时候,第一面就是谈谈秒杀业务,相信大家看了本文,再加以理解,在BAT这些大厂面试的时候,不会差!
今天我们继续通过SQL中的悲观锁来解决秒杀业务中商品超卖问题。
之前那篇文章已经提到了,MySQL悲观锁中的排它锁for update也可以解决此问题。
复习
在进入本篇之前,我们先来复习下悲观锁中的排它锁。
- 排它锁关键字:for update
- 特点:会锁住行或者表,防止其他事务进行修改操作或者获取锁操作。
详见:步步揭秘:MySQL共享锁的特性-2
解决办法
该解决办法就是通过排它锁:for update进行操作
上述SQL可以通过下图进行展现:
- 线程1:在A时刻开始事务,并将goods_id为1的那一行锁住(行锁),然后进行查询,获取库存。
- 线程2:在B时刻也想进行同样的操作,先是开启事务,然后通过同样的SQL语句尝试获取goods_id为1的行锁。显然此时线程2不会成功,因为线程一在A时刻先对此行上了锁,线程2此时只能等待,等到线程1提交事务释放锁。
3.线程1:在A到D的这段时间里独占一行,进行操作;线程2因为无法获取到锁,所以只能 在B到D这段时间内进行阻塞等待。
4.线程1:在D时刻提交事务,释放了锁。
5.线程2:在C时刻重新获取此行的锁,然后进行后续操作,直到E时刻释放锁。
总结
减库存操作前,在查询的时候通过for update将需要操作的列锁住,直到当前线程操作完成,将事务提交后,其他线程的事务才能接着进行操作。
这就是一种独占思维:每一次只允许一个线程进行操作,其他想操作的线程,必须等我处理完后才能进行处理。
老样子,我在这里留点思考题,感兴趣的同学可以在评论区谈谈想法:
- 悲观锁有2种:排他锁和共享锁,本文是通过排它锁来防止超卖的,可以通过共享锁来实现防止超吗?
- 除了在数据库中通过悲观锁保证同一时间只有一个线程对某个资源进行操作,还有其他办法实现这样的功能吗?
下一盘文章会针对第二个问题进行探讨。原创文章,欢迎关注、收藏、点赞。