并发实际开发案例



1.案例

在score 积分表内,每次新增任务都会把之前任务的 score 分数累加,计算总积分 all_score

// score 表结构
CREATE TABLE `score` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) DEFAULT NULL COMMENT '用户ID',
  `task_id` int(11) DEFAULT NULL COMMENT '任务ID',
  `score` bigint(11) DEFAULT NULL COMMENT '任务积分',
  `all_score` bigint(11) DEFAULT NULL COMMENT '总积分',
  `status` tinyint(1) DEFAULT NULL COMMENT '状态',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

一般正常逻辑

// 查询所有任务积分
select sum(score) from  score where user_id = 1;
// 将任务积分添加至总积分中
insert into score ...

如果没有并发处理,同时有多个会话插入任务时

在计算总分时会出现错误


2.解决

使用事务,增加排他锁写锁,短暂的阻塞其他会话的执行

$this->start();
try{
    $sql = "select sum(score) from score where uid = 1 for update";
    $sql = "inster into ...";
    $this->commit();
}catch(Exception $exception){
    $this->rollback();
    return $exception->getMessage();
}

3.场景分析

  1. for update

    禁止其他事务在这些加了锁的行上进行操作

使用 for update 推演过程:

时间 会话 1 会话 2
1 select sum(score) from score where uid = 1 for update
2 插入数据 inster into ... select sum(score) from score where uid = 1 for update
3 事务提交 等待会话 1 释放写锁
4 插入数据 inster into ...
5 事务提交
  1. lock in share mode

    在读取到的行上设置共享锁,其他会话可以读取行,也可以继续给行加共享锁,但是在当前事务提交之前其他会话不能修改加了共享锁的行

    如果这些行被尚未提交的,另一个事务更改

    则当前查询将等待直到该事务结束,然后使用最新值

使用 lock in share mode 推演过程:

时间 会话 1 会话 2
1 select sum(score) from score where uid = 1 lock in share mode
2 插入数据 inster into ... select sum(score) from score where uid = 1 lock in share mode
3 等待会话2释放读锁 插入数据 inster into ...
4 继续等待 检测死锁
5 继续等待 回滚事务
6 事务提交

如果使用上述场景下会造成死锁

lock in share mode 的应用场景适合于两张表存在关系时的写操作

假如存在两张有关系的表:PARENT和CHILD

使用SELECT语句(快照读)来查询表PARENT并验证父行是否存在,后再将子行插入CHILD表

可能其他的会话会删除父行

我们使用加共享锁的方式执行

SELECT * FROM parent WHERE NAME = 'Jones' LOCK IN SHARE MODE;

就可以安全地将子记录添加到CHILD表中并提交事务。

其他会话都将等到你完成操作提交事务后再进行

posted @   linsonga  阅读(44)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示