MySQL处理高并发,防止库存超卖

其实mysql拍卖高并发,防止库存超卖的问题,在去年底时段,王总曾提了;但是非常惋惜,即使这大家都听明白了,但是于现实开发中,还是尚未立马上头的觉察。今天即使自己的有知情,整理一下此问题,并要以后这样的教程能多触及。

 

预先来即使库存超卖的题目作描述:一般电子商务网站都见面遇上如团购、秒杀、特价之类的运动,而如此的活动发出一个协办之性状就是访问量剧增、上千居然上万口抢购一个货。然而,作为移动商品,库存肯定是十分有限的,如何决定库存不叫出现超买,以备造成不必要之损失是过剩电子商务网站程序员头疼的题材,这同时为是最最核心的问题。

 

打技术上面分析,很多丁自然会想到事务,但是工作是决定库存超卖的必要条件,但不是尽量必要条件。

举例:

总库存:4个商品

请求人:a、1个商品 b、2个商品 c、3个商品

先后如下:

beginTranse(开启事务)
try{
    $result = $dbca->query('select amount from s_store where postID = 12345');
    if(result->amount > 0){
        //quantity为请求减掉的库存数量
        $dbca->query('update s_store set amount = amount - quantity where postID = 12345');
    }
}catch($e Exception){
    rollBack(回滚)
}
commit(提交事务)

上述代码就是咱们平常决定库存写的代码了,大多数人口犹见面如此写,看似问题未杀,其实暗藏在巨大的纰漏。数据库的看其实就算是针对磁盘文件之顾,数据库被的表其实就是保留于磁盘上之一个个文书,甚至一个文书包含了差不多张表。例如由于高并发,当前发出三只用户a、b、c三独用户进入到了这个工作中,这个上会出一个共享锁,所以当select的下,这三个用户查到的库存数量还是4只,同时还要小心,mysql
innodb查及的结果是有版本控制的,再其他用户更新没有commit之前(也就是没有起新本子之前),当前用户查到的结果还是不怕本;

 

接下来是update,假如这三个用户同时到达update这里,这个时节update更新报告句会管并发串行化,也即是为同时到达此处的是三只用户排个程序,一个一个执行,并生成排异锁,在时下者update语句commit之前,其他用户等待执行,commit后,生成新的版;这样实行完毕后,库存肯定啊负数了。但是因以上描述,我们修改一下代码就不见面并发超买现象了,代码如下:

beginTranse(开启事务)
try{
    //quantity为请求减掉的库存数量    $dbca->query('update s_store set amount = amount - quantity where postID = 12345');
    $result = $dbca->query('select amount from s_store where postID = 12345');
    if(result->amount < 0){ throw new Exception('库存不足'); } }catch($e Exception){ rollBack(回滚) } commit(提交事务)

另外,更简短之措施:

beginTranse(开启事务)
try{
    //quantity为请求减掉的库存数量    $dbca->query('update s_store set amount = amount - quantity where amount>=quantity and postID = 12345');
}catch($e Exception){
    rollBack(回滚)
}
commit(提交事务)

1、在秒杀的情况下,肯定不可知如此高频率的失去念写数据库,会重造成性能问题的
须使缓存,将需秒杀的货放入缓存中,并行使锁来处理该出现情况。当接到用户秒杀提交订单的动静下,先以货物数递减(加锁/解锁)后更展开任何方的处理,处理失败当以数据递增1(加锁/解锁),否则表示交易成功。
当商品数递减到0时,表示商品秒杀了,拒绝其他用户的恳求。

 

2、这个肯定不克一直操作数据库的,会挂的。直接读库写库对数据库压力太非常,要因此缓存。
将你一旦出卖起之货物以10个商品放到缓存中;然后于memcache里设置一个计数器来记录请求数,这个请书而得因你要秒杀卖来底商品数为基数,比如你想卖来10单商品,只允许100只请求进入。那当计数器达到100之时,后面进去的就显秒杀完,这样好减轻你的服务器的下压力。然后因当下100个请求,先会的先得后付的提拔商品以秒杀完。

 

3、首先,多用户并发修改及同漫长记下时,肯定是后交由的用户以掩盖掉前者提交的结果了。

其一一直可以采用加锁机制去解决,乐观锁或者悲观锁。

乐观锁,就是于数据库设计一个本号的字段,每次修改都使其+1,这样在付出时比较对交付前的版本号就清楚是无是出现提交了,但是生个毛病就是只能是动被控制,如果起跨应用修改和同长达数据乐观锁就从未办法了,这个上可考虑悲观锁。

悲观锁,就是直以数据库层面将数据锁死,类似于oralce中使select
xxxxx from xxxx where xx=xx for update,这样任何线程将无法提交数据。

除加锁之法门也可以使用收取锁定的方,思路是当数据库被统筹一个态标识位,用户以针对数码进行修改前,将状态标识位标识为在编写的状态,这样其他用户要编写这条记下时系统将发现出其他用户正在编写,则不容其修的请求,类似于你于操作系统中某文件在推行,然后你若修改该公文时,系统会唤醒你该公文不可编辑或删除。

 

4、不建议于数据库层面加锁,建议经劳务端的外存锁(锁主键)。当有用户若改某只id的多寡时,把要改的id存入memcache,若其他用户触发修改者id的数经常,读到memcache有这个id的价时,就拦住那个用户改。

 

5、实际利用被,并无是为mysql去直给大并发读写,会拄“外力”,比如缓存、利用主从库实现读写分离、分表、使用队列写入等艺术来下滑并发读写。

 

本文链接http://blog.csdn.net/caomiao2006/article/details/38568825

重新多参考情节:http://www.roncoo.com/article/index?tn=Mysql

网站地图xml地图