这篇文章我们就简单讲解一下文件锁和数据库锁的用法。
共享锁
接着我们释放锁,会发现那个等待的客户端的更新语句被执行了,释放锁的命令:unlock tables;
我们重新把num修改为1,然后在一个客户端里面加一个写锁,命令:lock table demo write;
然后在加写锁的这个客户端里面查询数据,命令:select * from demo; 结果如下:
然后在加写锁的客户端里面执行更新,把num修改为3,命令:update demo set num = 3 where i = 1; ,结果如下:
我们发现加了写锁的客户端是可以对数据进行任何操作的,接着我们用另外一个客户端,对数据进行查询,命令:select * from demo; 这个时候我们发现客户端处于等待状态,并没有执行读取,我们强制关闭等待,然后执行更新操作,把num修改为4,命令:update demo set num = 4 where id = 1; 同样发现也是处于等待状态,这个时候我们去另外一个客户端释放锁,命令:unlock tables; 这时候我们发现处于等待状态的更新操作执行了。
我们模拟真实场景的商品售卖,比如我们现在库存有10件商品,也就是我们设计demo表中id为1的商品数量num为10,我们购买的时候查询这个num,如果这个num是0了,那么我们就给用户提示商品售罄,如果是并发不高一个一个用户购买,那肯定是没有问题的,但是如果很多用户一起下单,就会出现超卖的情况,也就是这个num会变成负数,换句话说就是成功购买的用户将会超过10个,我们来看代码:
代码比较简单,相信大家也是可以看懂的,并发数少的时候这个代码是不会出现问题的,我们直接用apache的ab测试工具,来模拟一百个用户抢购这10个商品,看看会发生什么情况:
我们在看看数据库中的num
这个时候我们发现num竟然变成负数了,也就意味着超卖了3个。
文件锁和数据库锁一样,分为读锁和写锁,也就是共享锁和排它锁,还有就是可以有非租塞模式,如果是数据库锁的话就是有请求对数据库加锁了,那么其它请求需要等待别人完成请求才能执行数据库操作,文件锁的非租塞模式就可以不用等待直接返回操作不了数据库,例如我们都去抢购一个产品,如果别人加锁了,那么我们就可以得到系统繁忙的提示,相信大家也可以理解这个功能,下面我们直接来实现文件锁的写锁:
同样的我们使用ab测试工具进行测试,结果一样不会发生超卖的情况。
我们再简单说一下数据库按照粒度区分的三种锁:表级锁、行级锁、页级锁
行级锁:只会锁定要操作的数据,冲突少,但是速度慢,效率低,总结起来就是:开销大、加锁慢、粒度最小、会死锁、冲突最低、并发度高;
特别注意:行级锁是一种类似建议锁的机制,使用的时候需要先检查锁,也就是每个事务都要在查询语句里面写for update,官方的解释过于简单,普通select语句默认不加锁,CUD语句默认写锁,想了解更多,自行搜索建议锁和强制锁。不同数据库实现行级锁的机制不太一样,mysql的行级锁是用索引条件加锁,也就是查询条件用到了索引就是行锁,其它的全部表级锁。
制图网(www.makepic.net),专业的logo免费设计在线生成网站,全自动智能化logo设计,商标设计,logo在线生成!
欢迎使用制图网制作属于您公司自己的logo,不仅专业而且经济实惠,全方位满足您公司品牌化、视觉化的需求。