高并发解决方案之 mysql悲观锁:select ... for update

2023-03-08,,

select ... for update

场景:多个进程都先读后写咋办,需要的是让他们串行执行。

比如库存的减少。一般这些操作都是很长一串并且是开启事务的。如果库存刚开始读的时候是1,而立马另一个进程进行了update将库存更新为0了,而事务还没有结束,会将错的数据一直执行下去,就会有问题。所以需要for upate 进行数据加锁防止高并发时候数据出错。

特点:for update仅适用于InnoDB,且必须在事务块(BEGIN/COMMIT)中才能生效。在进行事务操作时,通过“for update”语句,MySQL会对查询结果集中每行数据都添加排他锁,其他线程对该记录的更新与删除操作都会阻塞。排他锁包含行锁、表锁。

原理: 多个进程试图通过for update给表加锁,但只有一个能获取到。那就要等待上一个 commit提交之后才能select到数据。

悲观

悲观锁是对数据被的修改持悲观态度(认为数据在被修改的时候一定会存在并发问题),因此在整个数据处理过程中将数据锁定。悲观锁的实现,往往依靠数据库提供的锁机制(也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在应用层中实现了加锁机制,也无法保证外部系统不会修改数据)。

项目中应用:

在砍价微服务中对 好友砍价的功能应用此悲观锁。 刚开始查询砍价分支信息,如果合法,则允许砍价,更改分支信息(其中也涉及库存数量)。这个过程中用户请求可能比较集中,就要避免高并发的问题。

点击查看代码
 public function cutBranch()
{
$branchId = ...;
try {
Db::beginTransaction();
$data = $this->bargainBranchLogic->cutBranch(branchId);
} catch (\Throwable $e) {
//...
Db::rollback();
}
Db::commit();
//...
} public function getBranchInfoForUpdate($con){
$tbName = ...;
$data = Query::table($tbName)->forUpdate()->condition($con)->one()->getResult();
var_dump(get_last_sql());
return self::format($data);
}

高并发解决方案之 mysql悲观锁:select ... for update的相关教程结束。

《高并发解决方案之 mysql悲观锁:select ... for update.doc》

下载本文的Word格式文档,以方便收藏与打印。