使用模型类,调用lock()方法, 参数true是全局范围的,false只是当前链接
lock()调用会在sql语句后面,加上“for update”.
lock生效的条件,必须方式一个事务中,可以使用所有表开启Db::stratTrans(),Db::commit()之后锁表结束
//单个表事务
$user = new User();
$db = $user->db(true);
$db->startTrans();
$res = $user->lock(true)->where(["id" => 1])->field(‘mobile,username‘)->find();
sleep(3); // 休眠3秒,ID=1的行会锁表3秒
$db->commit();
//多个表事务
Db::stratTrans();
User::lock(true)->where(["id" => 1])->field(‘mobile,username‘)->find();
sleep(3); // 休眠3秒,ID=1的行会锁表3秒
Db::commit();//或者回退也是户释放的,Db:rollback();
lock生效过程中,其他的并发请求中的Update操作都会出于阻塞,等待的状态
lock使用的注意事项,lock的条件,一定要用主键或唯一索引键,否则容易导致,整个表被锁住,而导致其他服务都出于等待中。原因,下面会讲。
for update是在数据库中上锁用的,可以为数据库中的行上一个排它锁。当一个事务的操作未完成时候,其他事务可以读取但是不能写入或更新。
InnoDB默认是行级别的锁,当有明确指定的主键时候,是行级锁。否则是表级别。
for update 仅适用于InnoDB,并且必须开启事务,在begin与commit之间才生效。
锁的具体实例,假设表foods ,存在有id跟name、status三个字段,id是主键,status有索引。
明确指定主键,并且有此记录,行级锁
SELECT * FROM foods WHERE id=1 FOR UPDATE;
SELECT * FROM foods WHERE id=1 and name=’咖啡色的羊驼’ FOR UPDATE;
明确指定主键/索引,若查无此记录,无锁
SELECT * FROM foods WHERE id=-1 FOR UPDATE;
无主键/索引,表级锁。影响非常大
SELECT * FROM foods WHERE name=’咖啡色的羊驼’ FOR UPDATE;
主键/索引不明确,表级锁。影响非常大
SELECT * FROM foods WHERE id<>’3’ FOR UPDATE;
SELECT * FROM foods WHERE id LIKE ‘3’ FOR UPDATE;
for update nowait 锁住表或者锁住行,只允许当前事务进行操作(读写),其他事务被拒绝,事务占据的statement连接也会被断开
thinkphp中的lock与mysql的for update的使用注意事项
原文:https://www.cnblogs.com/qumogu/p/14826050.html