MySQL并发处理

在TP下的实验:

public function mysql_a()
{
    db('goods')->where('id',2)->setInc('num');
    $info = db('goods')->where('id',1)->find();
    sleep(1);
    if( $info['num']>0 ){
        db('goods')->where('id',1)->setDec('num');
    }    	
}

模拟并发请求:


执行前:


执行后:


压测结果:


如果当前为抢购或秒杀场景,此时就会出现超卖情况。




解决方案:

public function mysql_a()
{
    // 启动事务
    \Db::startTrans();
    try {
        \Db::name('goods')->where('id',2)->setInc('num');
        $num = \Db::name('goods')->where('id',1)->lock(true)->value('num');
        sleep(1);
        if( $num>0 ){
	    \Db::name('goods')->where('id',1)->setDec('num');
    	}
	// 提交事务
	\Db::commit();
    } catch (\Exception $e) {
        // 回滚事务
	\Db::rollback();
    }
}

压测结果:

加上lock(true)的实际就是在查询语句最后加上 for update(必须跟事务同时使用),此时新开窗口再次查询加锁这条数据,你会发现另一个窗口的查询会一直等待,直到第一个窗口的事务提交。

猜你喜欢

转载自blog.csdn.net/qw_xingzhe/article/details/80964791