在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(必须跟事务同时使用),此时新开窗口再次查询加锁这条数据,你会发现另一个窗口的查询会一直等待,直到第一个窗口的事务提交。
本文探讨了在高并发抢购场景中,如何通过在PHP中使用MySQL事务和`lock(true)`实现数据一致性,避免超卖问题。作者介绍了不加锁与加锁操作的压测对比,并强调了事务在并发控制中的关键作用。

被折叠的 条评论
为什么被折叠?



