注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

@fc_lamp

关注Web应用解决方案MySql/PHP/Python一盏名为"飞川"的灯~

 
 
 

日志

 
 

关于 mysql innodb 中的 select update 锁机制问题(如何更好处理 select...from ..update..问题)  

2016-05-20 00:13:45|  分类: Web技术-Mysql |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
我们经常会有这样(或者类似)的业务逻辑:一个商品在购买时,如果有库存时,其状态为1。或者说是:获取出所有有库存的商品,将其状态设置为1。又或者说:点赞业务。
我们一般常用的做法是 
SELECT quantity FROM products WHERE id=3; 
UPDATE products SET status= 1 WHERE id=3;

上面这两条语在并发量不高的情况下,这样做是没有任何问题的。但一高并发下,这样做就会有问题,因为在你做update之前
可能id  为 3 的库存已被其他用户抢完了。

解决方案:
mysql 中是没有select from ....update set....这样的语句的,只能通过锁机制来处理这个问题。

一 使用mysql中的悲观锁
 使用悲观锁主要就是使用数据库提供的锁机制来处理。我们使用Innodb为例,因为Innodb可以在某条件使用行锁。
InnoDB行锁实现方式:
在不通过索引条件查询的时候,InnoDB确实使用的是表锁,而不是行锁,由于MySQL的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不同行的记录,但是如果是使用相同的索引键,是会出现锁冲突的。当表有多个索引的时候,不同的事务可以使用不同的索引锁定不同的行,另外,不论是使用主键索引、唯一索引或普通索引,InnoDB都会使用行锁来对数据加锁(即建立在索引上)
 参:http://book.51cto.com/art/200803/68127.htm
我们需要在事务中使用SELECT ... LOCK IN SHARE MODE 或者 SELECT ... FOR UPDATE 实现读取时加锁。
这两种方式在事务(Transaction) 进行当中SELECT 到同一个数据表时,都必须等待其它事务数据被提交(Commit)后才会执行。
另外:使用锁时,最好是关闭数据库的自动提交。
eg:

set autocommit=0;

start transaction;

SELECT quantity FROM products WHERE id=3 for update;

//这里处理其事务........

commit;

缺点:影响并发性能。

二 在业务层使用乐观锁:
     乐观锁则认为其他用户企图改变你正在更改的对象的概率是很小的,因此乐观锁直到你准备提交所作的更改时才将对象锁住,当你读取以及改变该对象时并不加锁。如果发现冲突了,则让返回用户错误的信息,让用户决定如何去做。
   即在做更新操作时,再比对使用的对象。

缺点:需要再获取一次对象。

  评论这张
 
阅读(81)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017