【学习笔记】MySQL死锁及热点行问题

目录

      • 案例
      • 优化思路
      • 死锁的一些记录笔记
      • 热点行问题

本文记录下关于MySQL优化的学习和一点点思考。

案例

一个并发比较大的下单接口;
包括

  • step1 扣减商品库存
  • step2 生成订单数据
  • step3 记录操作记录

伪代码如下,底层使用的是MySQL数据库,单体服务(你问我为什么单体,案例需要啦)。

提问:暂时不考虑分布式锁、缓存、异步等使用场景,下面的代码执行步骤有没有值得优化的点?

  @Transactional(rollbackFor = Exception.class)
  public void createOrder(Entity param){
       ...校验等
      //step1 扣减商品库存
      //update products set stock = stock where sku_id = XXX
      deductStock(param);
      //step2 生成订单数据
      //insert into order XXXXXX
      createOrder(param);
      //step3 记录操作记录
      //insert into operation_records XXX
      recordOperation(param);
      ... 
  }

上述代码做了哪些事,开启了事务

更新了一个个表:库存表库存分

插入了两条数据:用户订单表,用户操作记录

对于当前的业务,上述代码的DB执行流程是没有问题的,

但是朋友,我们是要有梦想滴,CRUD BOY不是我们的终点,我们的目标是星辰大海。

来,键盘给你,优化下。

优化思路

正常业务情况下,上述代码没毛病,开启事务,库存更新语句会加上行锁,插入语句可能会加上插入意向锁等。

我们重点来关注下 更新语句的行锁,并发高的情况下,同一种库存商品数据是根据sku_id来更新,存在激烈的行锁竞争抢占的问题。

来回忆一下,MySQL事务开启后,是什么时候开始给库存加行锁的?

事务开启就加行锁? 错。
是在执行更新语句的时候加锁的,上述的step1

那么解锁是什么时候呢?

当然是事务提交的时候。

那么对于案例中的语句来说,products表的sku_id = XXX这行数据的行锁,将从step1开始锁定,直到createOrder()方法执行完毕才会解锁。

对于其他的创建订单请求,热点商品,相同的sku_id,同时执行这行代码的时候,只能等待。

这样分析可以发现,持有锁的时间太长了。

没错,是时间太长了,换个场景,或许我会欣喜若狂,彷佛得到了认可,

但此时此刻,这并不是我想要的。

那么,是否可以将更新库存的语句放到最后呢,step1 变成step3,这样对一一次创建订单的请求,加锁的时长会大大减少,并发度会提升。

  @Transactional(rollbackFor = Exception.class)
  public void createOrder(Entity param){
       ...校验等
      //step1 生成订单数据
      //insert into order XXXXXX
      createOrder(param);
      //step2 记录操作记录
      //insert into operation_records XXX
      recordOperation(param);
      //step3 扣减商品库存
      //update products set stock = stock where sku_id = XXX
      deductStock(param);
      ... 
  }

这样的优化虽不起眼,但是架不住积少成多,从细节处着手,才能仰望星空。

这样才是泰裤辣!

死锁的一些记录笔记

继续讨论下,上述代码没有问题了,但是

职业生涯中,我并没有真正的面对过MySQL的死锁,很幸运也很不幸,无需面对老大难的风险,但也没有获得实操的经验。

死锁的产生及竞态条件不再赘述。

最接近死锁的一次,还是刚工作的时候在一家保险公司,我还是nobody,当然了现在也还是nobody。

大约记得夜里的批处理更新账户信息,以及客户投保时,都需要保险账户总表账户明细表更新,批处理和客户投保的请求互相竞争对方持有的锁,导致死锁,疯狂报警,处理方案则是DBA大半夜爬起来 kill掉其中一个session,解除死锁。

很明显上述处理的方案是不可持续的。

完全避免死锁不太现实,我们需要做的是尽可能减少死锁发生的概率。

MySQL给我们提供了两种方案

  • 互相等待锁释放,直至超时,通过innodb_lock_wait_timeout来设置
  • 死锁检测,innodb_deadlock_detect设置为on (8.0之后版本提供)

第一种策略,我们固然可以设置很短的超时时间,但是对于慢SQL来说很容易误伤。

所以一般会有第二种方案,超时检测。
MySQL会自动查询是否存在连接相互等待获取对方连接的情况,如果存在,会回滚其中一个事务来打破死锁。

但是高并发情况下,比如上述的案例接口,死锁检测会影响到MySQL执行速度和效率,我们就只能通过第一这种方案来等待超时释放。

热点行问题

正如我们上面讨论的,案例中的某个热门产品的库存对于MySQL来说就是热点行,会存在频繁的锁竞争死锁等问题,会导致性能下降,MySQL本身也没有更好的方案来避免。

我们考虑下从业务层来解决这个问题。

  • redis预扣减

使用redis缓存热点商品,借助redis的高性能、高并发特性,承担大部分的请求压力。

但是redis会增加复杂度,可能会带来数据不一致的情况,例如超卖和少卖。

  • 库存拆分

往往库存只有一条数据,作为共享资源,为了保证安全,MySQL会对这条数据加锁,请求只能排一条长队等待锁的释放,如果我们把这条数据拆分成多条,10条数据,20条数据,性能的提升是可以预见的,大量请求的锁竞争可被分散在多条数据上,请求的耗时根据拆分的力度逐渐降低。

拆分缺点也很明显,对于拆分后的数据,某条库存用完了怎么办,怎么判断库存超卖不超卖,以及库存数据的增加维护等等等,系统复杂度会提升。

  • 请求合并

对于反馈需要及时的电商场景,请求合并并不一定适合,但是对于实时性没那么强的业务场景,比如说银行或者保险的热点账户,多个账户变动请求同时变更同一个账户,我们可以在1s、5s或者更长一段时间内将这段时间的多个请求在内存中计算合并后,再去更新数据库,可以大大降低数据库的压力。

  • 更新转插入

这种方式也是针对异步场景 UPDATE语句转INSERT语句,原来更新一条数据,改为插入单独的一个明细表,通过异步的方式将明细表进行汇总计算,再合并到原数据中。

这么一想设计思想是否和MySQL redo log的使用方式比较接近了,先顺序写磁盘,然后异步写入MySQL数据表中。
很多设计思想都是一致的,无非是实现的区别

理论上我们上述说的方案,也都可以通过MySQL进行改造,比如请求合并,改为在MySQL层对相同的SQL语句(这里的相同指更新逻辑基本一致)进行合并。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/127930.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

家政系统、家政小程序

家政系统、家政小程序。提供线上下单,订单微信提醒,手机端一键派单,保姆月嫂人员展示,预约。拼团、秒杀、分销等营销功能。系统管理订单,人员,财务。

微头条项目实战:新增RequestHeader注解

1、RequestHeader package com.csdn.mymvc.annotation; import java.lang.annotation.*; Target(ElementType.PARAMETER) Retention(RetentionPolicy.RUNTIME) Inherited public interface RequestHeader { }2、DispatcherServlet package com.csdn.mymvc.core; import com.csd…

外贸SEO外链类型有哪些?外链建设如何做?

外贸SEO外链资源怎么找?海洋建站SEO外链优化方法? 外贸SEO外链在提高网站排名、吸引流量、增加品牌曝光方面发挥着重要作用。海洋建站将探讨外贸SEO外链的不同类型,帮助外贸企业更好地理解如何优化他们的在线营销策略。 外贸SEO外链&#x…

centos配置docker环境

CentOS系统更换软件安装源 yum默认链接的还是国外的镜像,速度相对不理想,配置成国内的镜像会快很多,这里以阿里镜像为例进行配置: 首先进行更新: yum updatebase源 第一步:备份你的原镜像文件,以免出错后…

工厂设备报修的流程是怎样的?维修流程要如何优化?

在当今高度自动化的生产环境中,工厂设备的正常运行无疑对于企业的生产效率和经济效益具有至关重要的影响。然而,设备故障是生产过程中不可避免的现象。当设备发生故障时,如何快速、有效地进行报修、维修,以恢复设备的正常运转&…

Activiti

序言 activiti是一个工作流引擎,可以将业务系统中复杂的业务流程抽取出来,使用专门的建模语言BPMN进行定义(所以我们也需要了解BPMN相关信息),业务流程按照预先定义的流程进行执行。实现了系统的流程由activiti进行管理,减少业务系…

Linux--信号

一.引号的产生 1.什么是信号 在生活中,信号的产生是多种多样的,比如红绿灯,闹钟等等,Linux中的信号是什么呢? 1.在Linux中,信号的本质是一种通信方式,由用户或操作系统发送信号,通知…

性格软弱怎么办?如何改变性格软弱?

软弱指的是身体衰弱无力气,而这里要说的是性格软弱,性格软弱的人,大多是不自信的,无主见,容易妥协,害怕产生矛盾,遇到问题就想逃避,自我否定,担心自己这也不行那也不行。…

vue+css动画 实现文字的上下轮播切换

突然间碰到一个比较丝滑的特效,就研究了一下想把它实现出来。 效果:渐隐消失,底部往上走覆盖出现 以下是完整代码,复制粘贴即可运行 <template><div class="aaa"><divclass="page1":class="{ private-fade-out: prevIndex === 1…

代码随想录算法训练营第四十七天丨 动态规划part10

121. 买卖股票的最佳时机 思路 动态规划 动规五部曲分析如下&#xff1a; 确定dp数组&#xff08;dp table&#xff09;以及下标的含义 dp[i][0] 表示第i天持有股票所得最多现金 &#xff0c;这里可能有疑惑&#xff0c;本题中只能买卖一次&#xff0c;持有股票之后哪还有…

Python大语言模型实战-利用ChatDev框架自动开发一个游戏软件(附完整教程)

实现功能 ChatDev一个由多智能体协作框架&#xff0c;是一个虚拟软件公司&#xff0c;在人类 “用户” 指定一个具体的任务需求后&#xff0c;不同角色的智能体将进行交互式协同&#xff0c;以生产一个完整软件&#xff08;包括源代码、环境依赖说明书、用户手册等&#xff09…

利用IP风险画像强化金融行业网络安全防御

在数字化时代&#xff0c;金融行业日益依赖互联网和技术创新&#xff0c;但这也使得金融机构成为网络攻击的主要目标。为了应对日益复杂的网络威胁&#xff0c;金融机构迫切需要采用先进的安全技术和工具。其中&#xff0c;IP风险画像技术成为提升网络安全的一项重要策略。 1.…

若依分离版——使用Knife4j 自动生成接口文档

背景&#xff1a; 前后端分离程序&#xff0c;如果需要前端开发人员和后端开发人员配合开发&#xff0c;则需要将接口文档并显性给前端人员 解决办法&#xff1a; 使用knife4j替代若依自带的swagger&#xff0c;因为knife4j是在swagger基础上包装的&#xff0c;Knife4j不仅具…

Django生鲜蔬菜采购系统-计算机毕设 附源码 24033

Django生鲜蔬菜采购系统 目 录 摘要 1 绪论 1.1 研究背景 1.2国内外研究现状 1.3论文结构与章节安排 2 生鲜蔬菜采购系统系统分析 2.1 可行性分析 2.1.1 技术可行性分析 2.1.2 经济可行性分析 2.1.3 操作可行性分析 2.2 系统流程分析 2.2.1 数据流程 3.3.2 业务流…

react类式组件的生命周期和useEffect实现函数组件生命周期

概念 生命周期是一个组件丛创建,渲染,更新,卸载的过程,无论是vue还是react都具有这个设计概念,也是开发者必须熟练运用的,特别是业务开发,不同的生命周期做不同的事是很重要的. ....多说两句心得,本人是先接触vue的,无论是vue2还是vue3的生命周期,在理解和学习上都会比react更…

【三维重建】摄像机几何

针孔相机模型 为了方便我们对针孔相机模型进行数学建模&#xff0c;我们往往对虚拟像平面进行研究&#xff0c;因为虚拟像平面的方向与我们实际物体的方向一致。 通过相似三角形法可以得到三维坐标到二维坐标映射 将像平面原点坐标移动到左下角&#xff1a; 加上现实世界单位&a…

Excel表列序号

题意&#xff1a; 给你一个字符串 columnTitle &#xff0c;表示 Excel 表格中的列名称。返回 该列名称对应的列序号 。 例如&#xff1a; A -> 1 B -> 2 C -> 3 … Z -> 26 AA -> 27 AB -> 28 … 示例 1: 输入: columnTitle “A” 输出: 1 示例 2: 输…

植物补光灯,哪种效果好?

室内种植物有诸多好处&#xff1a;空间装饰、吸收有害物质、释放氧气&#xff0c;使室内空气更加清新&#xff1b;植物的蒸腾作用可以增加室内的湿度&#xff0c;改善秋冬季干燥的室内环境&#xff0c;可谓是天然的加湿器。 然而由于缺乏太阳光&#xff0c;在室内养植并不是一…

Matlab设置figure中标题/图例英文不同字体

1.创建一个曲线图 x linspace(-10,10,200); y sin(4*x)./exp(x); plot(x,y) xlim([0 10]) ylim([-0.4 0.8]) xlabel(a); ylabel(b); title(曲线图sapi); set(gca,FontName,Times New Roman,fontsize,16); legend(曲线12)标题中既包含英文又包含中文&#xff0c;如果设置字体…

玩具品牌的国际化之路:市场推广战略解析

玩具产业一直是全球市场中备受瞩目的领域之一。随着全球化的发展和互联网的普及&#xff0c;越来越多的玩具品牌开始进军国际市场。这既是机遇&#xff0c;也是挑战。在竞争激烈的全球市场中&#xff0c;如何成功推广玩具品牌是一个关键的问题。本文Nox聚星将和大家探讨玩具品牌…