因为最近在做公司的一个秒杀项目,就是现在一些购物网站最常见的那种。但是考虑到并发的一些问题(也许并发不是主要的,主要的是现在有秒杀就会出现秒杀工具之类的)导致被秒出去的商品比实际库存还要多,所以就上网看了一下mysql的锁,公司用的是innodb引擎,thinkphp3.2框架,根据网上的相关资料,应该用的是行级锁(对于mysql,本人菜鸟,懂的不是很深入)。
public function test_sql(){
set_time_limit(0);
$model = D('Liren/GroupPurchase');
$row = $model->lock(true)->where(array('id'=>1))->find();
if($row){
dump($row);
sleep(10);
}
}
test_sql 方法是带锁查询了一条数据,之后延时了十秒,在这同时,我开了另一个进程:
public function test_lock(){
$model = D('Liren/GroupPurchase');
$info = $model->find(1);
if($info){
dump($info);
}
}
在test_sql没有结束之前test_lock一直在等待。而且就算我在test_lock方法中查询的不是主键(id)为1的数据,也同样要等到test_sql结束之后才能执行。这样的话是不是整个表都锁住了,是不是需要继承thinkphp的AdvModel才能真正实现行级锁?
还有一个问题。事务和锁之间存在关系吗?
public function test_sql(){
set_time_limit(0);
$model = D('Liren/GroupPurchase');
$model->startTrans();
$row = $model->lock(true)->where(array('id'=>1))->find();
// echo $model->getLastSql();
if($row){
$ret = $model->lock(true)->save(array('id'=>1,'is_show'=>0));
echo $model->getLastSql();
}
if($ret){
$model->commit();
sleep(10);
echo 'success';
}
}
虽然事务是提交了,数据库的状态也一早就改变了,但还是必须等到test_sql进程结束之后 test_lock 方法才能输出数据,如果能在事务结束的时候表锁就能结束,这样是不是好一点。
小弟愚钝,望指点!
Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
1.innodb 引擎支持行锁,但是不指定唯一索引键就会锁表
test_sql 中,使用了悲观锁,也就是 select where for update
当 where 条件指定了唯一索引键时---行锁
当非唯一索引键时---表锁
2.在事务中
select 操作共享锁
update,delete,insert 排它锁
commit 会把锁给取消