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

目录

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

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

案例

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

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

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

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

  @Transactional(rollbackFor = Exception.class)public void createOrder(Entity param){...校验等//step1 扣减商品库存//update products set stock = stock where sku_id = XXXdeductStock(param);//step2 生成订单数据//insert into order XXXXXXcreateOrder(param);//step3 记录操作记录//insert into operation_records XXXrecordOperation(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 XXXXXXcreateOrder(param);//step2 记录操作记录//insert into operation_records XXXrecordOperation(param);//step3 扣减商品库存//update products set stock = stock where sku_id = XXXdeductStock(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语句(这里的相同指更新逻辑基本一致)进行合并。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OFDM深入学习及MATLAB仿真

文章目录 前言一、OFDM 基本原理及概念1、OFDM 简介2、子载波3、符号4、子载波间隔与符号长度之间的关系 二、涉及的技术1、保护间隔2、交织3、信道编码4、扩频5、导频6、RF(射频)调制7、信道估计 三、变量间的关系四、IEEE 802.11a WLAN PHY 层标准五、…

84 柱状图中的最大的矩形(单调栈)

题目 柱状图中的最大的矩形 给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。 求在该柱状图中,能够勾勒出来的矩形的最大面积。 示例 1: 输入:heights [2,1,5,6,2,3] 输出:10 …

前端-选中DOM定位源代码

用到的工具:react-dev-inspector 使用流程 根据react-dev-inspector文档进行配置 安装 yarn add --dev react-dev-inspector配置:在根目录下配置Inspector import { createRoot } from react-dom/client import { Inspector } from react-dev-inspe…

0004Java安卓程序设计-springboot基于APP的鲜花商城

文章目录 **摘 要****目录**系统设计开发环境 编程技术交流、源码分享、模板分享、网课教程 🐧裙:776871563 摘 要 本毕业设计的内容是设计并且实现一个基于APP的鲜花商城。它是在Windows下,以MYSQL为数据库开发平台,java技术和…

【Java】基于SpringBoot创建Web页面并热更新

😏★,:.☆( ̄▽ ̄)/$:.★ 😏 这篇文章主要介绍基于SpringBoot创建Web页面并热更新。 学其所用,用其所学。——梁启超 欢迎来到我的博客,一起学习,共同进步。 喜欢的朋友可以关注一下,下…

竞赛 目标检测-行人车辆检测流量计数

文章目录 前言1\. 目标检测概况1.1 什么是目标检测?1.2 发展阶段 2\. 行人检测2.1 行人检测简介2.2 行人检测技术难点2.3 行人检测实现效果2.4 关键代码-训练过程 最后 前言 🔥 优质竞赛项目系列,今天要分享的是 行人车辆目标检测计数系统 …

linux gdb 调试 常见调试命令介绍+总结

1.调试前准备 -g gcc arcg.c -g -oO -o app //必须添加-g 2.调试 gdb gdb app 3.常见调试命令 set args 1 2 3 4 5 6 //设置参数 show args //查看参数 3.1执行程序 1.start2. run gdb app set args 1 2 3 4 5 start //执行一行 c //继续执行 q…

【uniapp】通用列表封装组件

uniapp页面一般都会有像以下的列表页面,封装通用组件,提高开发效率; (基于uView前端框架) 首先,通过设计图来分析一下页面展示和数据结构定义 w-table组件参数说明 参数说明类型可选值默认值toggle列表是…

苹果转移供应链,促中国手机和中国制造更紧密合作,加速技术升级

随着苹果力推富士康等奔赴印度和越南设厂,引发的另一大反应恐怕是它所没有想到的,那就是中国手机和中国制造产业链的合作更加紧密了,中国制造产业链的技术水平反而因此得到提升。 一、产业链技术升级依赖苹果 对于制造产业链来说,…

【AntDesign】Docker部署

docker部署是主流的部署方式,极大的方便了开发部署环境,保持了环境的统一,也是实现自动化部署的前提。 1 项目的目录结构 dist: 使用build打包命令,生成的打包目录 npm run build : 打包项目命令 docker: 存放docker容器需要修改…

QT第2课-GUI程序实例分析

GUI程序开发概述 不同的操作系统GUI开发原理相同不同的操作系统GUI SDK 不同 GUI 程序开发原理 GUI程序在运行时会创建一个消息队列系统内核将用户的键盘鼠标操作翻译成对应的程序消息程序在运行过程中需要实时处理队列中的消息当队列中没有消息时,程序将处于停滞…

详解静态成员变量以及静态成员函数

一、静态成员变量 类的静态成员变量是该类的所有对象共有的(只有一份),只能在类里声明,类外定义。 相当于只属于类的全局变量。 1、定义: 只能在全局中定义 2、访问方式:(假如类A 中有公有静态变量 _a) ,可以用 A::_a 或 A a; a._…

【Unity】简单案例脚本实现 | 鼠标观察/键盘控制移动飞行/行走/碰撞检测

《Unity5实战-使用C#和Unity开发多平台游戏》第二章-构建一个让你置身3D空间的演示 鼠标观察/键盘控制移动飞行/行走/碰撞检测 Unity版本:2019.4.23f1c1 注意脚本名称和组件添加,不在文章中一一强调场景模型都是在资源商店选择的免费下载(选…

Vite创建React项目,另外一种更加简单的方法

在上一篇blog中一个一个安装依赖dependencies,有没有一步到位的方法呢,有! 参考《React 18 Design Patterns and Best Practices Design, build, and deploy production-ready web applications with React》4th 第一章倒数第二节Vite as a solution有个…

wpf Grid布局详解 `Auto` 和 `*` 是两种常见的设置方式 行或列占多个单元格,有点像excel里的合并单元格。使其余的列平均分配剩余的空间

比如只有行的界面 <Window x:Class"GenerateTokenApp.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d"http://schemas.microsoft.com/exp…

Linux - 实现一个简单的 shell

前言 之前我们对进程的替换&#xff0c;进程地址空间等等的概念进行了说明&#xff0c;本篇博客会基于这些知识点来 实现一个简单的 shell &#xff0c;如有疑问&#xff0c;可以参考下述博客&#xff1a;Linux - 进程程序替换 - C/C 如何实现与各个语言之间的相互调用 - 替换…

Redis 键值类型及其存储结构

Redis 键值类型及其存储结构 键值类型 键的数据类型是字符串&#xff0c;值的类型有&#xff1a;字符串、列表、Hash、集合、有序集合。 键的存储和查找 Redis底层键的存储类似于Java中其他Hash存储结构&#xff1a;数组链表的组合。数组中存储的是Key Hash函数对数组长度取模…

响应式成人高考自考教育机构网站模板源码下载带后台

模板信息&#xff1a; 模板编号&#xff1a;30558 模板编码&#xff1a;UTF8 模板分类&#xff1a;学校、教育、培训、科研 适合行业&#xff1a;教育机构类企业 模板介绍&#xff1a; 本模板自带eyoucms内核&#xff0c;无需再下载eyou系统&#xff0c;原创设计、手工书写DIVC…

解密Elasticsearch:深入探究这款搜索和分析引擎

•开篇 最近使用Elasticsearch实现画像系统&#xff0c;实现的dmp的数据中台能力。同时调研了竞品的架构选型。以及重温了redis原理等。特此做一次es的总结和回顾。网上没看到有人用Elasticsearch来完成画像的。我来做第一次尝试。 背景说完&#xff0c;我们先思考一件事&…

UseGalaxy.cn生信云平台文本文件操作手册

文本文件是生物信息学中应用非常广泛的文本格式&#xff0c;甚至可以说是最重要的文件格式&#xff0c;比如常见的测序下机数据Fastq、参考基因组保存格式Fasta、比对文件SAM&#xff0c;以及突变列表VCF&#xff0c;它们都是文本文件。熟练地进行文本文件的处理&#xff0c;对…