1. 云栖社区>
  2. PHP教程>
  3. 正文

mysql的行锁的另一种解决方案

作者:用户 来源:互联网 时间:2017-12-01 16:39:39

mysql解决方案

mysql的行锁的另一种解决方案 - 摘要: 本文讲的是mysql的行锁的另一种解决方案, 在网上看到一篇文章:原文如下:*************************************************************************************** 做项目时由于业务逻辑的需要,必须


在网上看到一篇文章:原文如下:***************************************************************************************

做项目时由于业务逻辑的需要,必须对数据表的一行或多行加入行锁,举个最简单的例子,图书借阅系统。假设id=1的这本书库存为1,但是有2个人同时来借这本书,此处的逻辑为

 Select   restnum  from  book  where  id =1 ;      -- 如果 restnum 大于 0 ,执行 update  Update   book  set restnum=restnum-1 where id=1 ;   

问题就来了,当2个人同时来借的时候,有可能第一个人执行select语句的时候,第二个人插了进来,在第一个人没来得及更新book表的时候,第二个人查到数据了,其实是脏数据,因为第一个人会把restnum值减1,因此第二个人本来应该是查到id=1的书restnum为了,因此不会执行update,而会告诉它id=1的书没有库存了,可是数据库哪懂这些,数据库只负责执行一条条SQL语句,它才不管中间有没有其他sql语句插进来,它也不知道要把一个session的sql语句执行完再执行另一个session的。因此会导致并发的时候restnum最后的结果为-1,显然这是不合理的,所以,才出现锁的概念,Mysql使用innodb引擎可以通过索引对数据行加锁。以上借书的语句变为:

Begin;  Select   restnum  from  book  where  id =1  for   update ;  -- 给 id=1 的行加上排它锁且 id 有索引  Update   book  set restnum=restnum-1 where id=1 ;  Commit;   

这样,第二个人执行到select语句的时候就会处于等待状态直到第一个人执行commit。从而保证了第二个人不会读到第一个人修改前的数据。*****************************************************************************************************文章的意思是想讲行级锁的应用,不过针对上面举的那个例子的那个场景(其实这种场景还是经常出现的比如,秒杀系统等)完全可以用修改下sql语句即可。 update   book  set restnum=restnum-1 where id=1 and restnum>0; 只要在原来的update 语句之后加一个 restnum>0 ,问题即可解决

以上是云栖社区小编为您精心准备的的内容,在云栖社区的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索mysql 解决方案 ,以便于您获取更多的相关知识。