这篇文章主要介绍了mysql 数据库innodb死锁原因及解决办法,需要的朋友可以参考下:
在一些涉及到数量扣减的业务场景中为了保持数据的一致性, 通常需要把一些不同资源(行或表)的插入或修改放在一个事务中提交给数据库, 这样在多并发情况下很容易造成死锁。
这里以订单和明细举例:
比如
订单
和多个
订单明细
对应不同的货物, 不同的订单会包含相同的货物, 这个大家容易理解吧,不同的人当然可以买同样的东西了。
下单环境是多并发这个应该没有异议了, 那这个时候存在
并发 + 相同资源的争夺,
产生死锁的高危环境。
当存在上图的两个线程, 这个时候就会产生(DeadLock), A和B互相锁住(
X锁
)了对方需要的必要资源, 死锁形成的具体机制可以参考上一篇文章。
这个时候数据库会检测到死锁同时kill其中一个线程, 通常是复杂度低资源少的线程。
如何预防避免当前场景下的死锁:
1. 提高线程的性能, 加快执行速度及时释放出资源。
2. 按顺序执行资源的修改, 简单的说按顺序执行对资源修改的sql语句。这个时候在线程A执行的时候占用了资源”库存1“, 线程B会等待锁, 但是双方并没有互相占用对方资源形成首尾互相衔接的死锁条件。因此在线程A执行完毕后,线程B会获得相应的资源完成提交,lock wait的时间默认一般是50秒, 所以要避免那种超长的批量提交。
经过分析: 该方法更新
库存
时更新缓冲区销量本身逻辑存在不合理的情况,
产生
了一定的耦合性, 所以吧更新t_item 操作统一放在定时任务批量操作,不再耦合在更新
库存
方法中, 这样就
解决
了 两张表不按照顺序更新时
产生
的
死锁
。如果不加索引, 锁的是整张表 , 针对这张表的任何更新操作都要等待锁释放,所以不要因为表数据量小就不加索引, 针对于频繁更新的字段更要加索引, 降低锁的粒度。事务 1 的等待锁 : t_product , 证明在其他事务中有对 t_product表的修改,还未提交。
本章节即将了解到,数据库锁的机制。锁这个概念在很多地方都
会
出现,如Python、Java等等编程语言内,而锁的目的也很简单,保证数据的安全性,但是也随之降低了效率,我们必须根据情况而定,如果追求安全性的情况下,就不能盲目追求效率,而MySQL作为数据库,存入在里面的必定是很重要的数据,如果了解锁的机制是很有必要的。
数据库的锁机制
什么是锁?为何要加入锁机制?
锁是计算机协调多个进程或线程并发访问某一资源的机制,那为何要加入锁机制呢?
因为在数据库中,除了传统的计算资源(如CPU、RAM、I/
OIS参考模型,每一层涉及到了哪些协议,每一层负责了什么?
最重要的就是传输层,这一块一定要好好看TCP的特点是什么?什么是窗口滑动协议,什么是快速重传,什么是拥塞避免,什么是慢启动?怎么做到可靠数据传输?TCP的流量控制是什么?如果RcvWindow=0应该怎么办?有哪几种定时器?作用分别是什么?TCP和UDP的区别?什么场景使用TCP...
锁定用于确保事务完整性和数据库一致性。 锁定可以防止用户读取其他用户正在更改的数据,并防止多个用户同时更改相同的数据。 如果不使用锁定,数据库中的数据可能在逻辑上变得不正确,而针对这些数据进行查询可能
会
产生
想不到的结果。
在计算机科学中,锁是在执行多线程时用于强行限制资源访问的同步机制,即用于在并发控制中保证对互斥要求的满足。在数据库的锁机制中介绍过,在DBMS中,可以按照锁的粒度把数据库锁分为行级锁(INNODB引擎)、表级锁(MYISAM引擎)和页级锁(BDB引擎 )。
行级锁是Mysql中
一、想要实现什么功能?点击商品购买按钮;扣
库存
;扣除用户的余额;给用户背包增加商品;二、可能
会
有高并发出现的场景?同一个用户,开启两个客户端,同时购买同一个商品;同一个用户,开启两个客户端,同时购买不同的商品;两个不同的用户,同时购买同一个商品;两个不同的用户,同时购买不同的商品;同一个用户,开启两个客户端,同时购买多个商品,一个客户端购买商品a、b,另一个客户端购买商品b、a不同的用户,同时购买...
欢迎大家关注公众号「JAVA前线」查看更多精彩分享文章,主要包括源码分析、实际应用、架构思维、职场分享、产品思考等等,同时欢迎大家加我个人微信「java_front」一起交流学习
1 基础知识
在电商系统中
扣减
库存
是一步非常关键的操作,例如秒杀系统中一定要防止超卖情况出现,如果商家设置了100件
库存
但是最后卖出1000件,这样就
会
产生
资金损失。在
扣减
库存
时一般使用如下语句:
udpate goods set stock = stock - #{acquire}
where sku_id = #{sk.
先说场景:物品W现在
库存
剩余1个,用户P1、P2同时购买,只有1人能购买成功,不允许超卖秒杀也是类似的情况,只有1件商品,N个用户同时抢购,只有1人能抢到这里不谈秒杀设计,不谈使用队列等使请求串行化,就谈下怎么用锁来保证数据一致性常见的实现方案有以下几种:1.代码同步, 例如使用 synchronized, lock 等同步方法2.不查询,直接更新 update table set surplus...
对于特定数量的商品,如何在高并发下进行
库存
锁定呢 ?
促销的商品数量有限,用户加入购物车后,实际
库存
就
会
减
少。那么,对于特定数量的商品,如何在高并发下进行
库存
锁定呢 ?
多宝家小主 笨土豆 产经 4 天前 18:36
首先先看你的锁
库存
,是加入购物车锁
库存
,生成订单锁
库存
,还是付款锁
库存
。
减
库存
可以采用同步调用(商品微服务提供接口,通过Feign调用),也可以采用异步调用(通过RabbitMq),我们采用同步调用,接下来我们来分析分析原因。
若采用异步调用的方式,我们要进行
减
库存
,只需向RabbitMq中发送消息即可,后续我们不管,但是否
减
库存
成功我们不得而知。若
库存
不足,则
减
库存
失败,但是订单微服务中并不知道
减
库存
失败,因此事务不
会
回滚,这就是分布式事务问题 (跨服务的事务)。我...
悲观锁就是利用数据库机制实现,一般利先通过for update的方式进行加锁,然后再进行修改。这就是比较典型的悲观锁策略。
乐观锁实现方式有一种比较典型的就是CAS(Compare and Swap)。乐观锁一般在where条件中限制。
CAS是项乐观锁技术,当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不
会
被挂起,而是被告知这次竞争中失败,并可以再次尝试。,
乐观锁一般自己通过sql实现,增加version字段,读取出数据时,将此版本号一
在日常交易场景中,我们有用户A向用户B进行转账,用户B向用户A进行转账的情况,那么当两个请求并发一起执行的时候怎么办呢,首先是在事务中绑定一个
死锁
。
$user1 = \App\Models\User::query()->where('id',1)->lockForUpdate()->first();
那么当
产生
死锁
之后我们怎么来处理呢。
* Notes:
死锁
1
* Author:tanyong
* DateTime:2022/5/19
先说场景:物品W现在
库存
剩余1个, 用户P1,P2同时购买.则只有1人能购买成功.(前提是不允许超卖)秒杀也是类似的情况, 只有1件商品,N个用户同时抢购,只有1人能抢到..这里不谈秒杀设计,不谈使用队列等使请求串行化,就谈下怎么用锁来保证数据正确.常见的实现方案有以下几种:1.代码同步, 例如使用 synchronized ,lock 等同步方法2.不查询,直接更新 update table...
项目上线后发现
死锁
问题,数据量级并不大,现将分析过程和
解决
方案整理一下,以作记录
场景:申购,赎回两个接口并发做
下单
操作
描述:并发
下单
操作时,频繁的更新同一张表同一条记录,导致
死锁
现象发生
问题分析:由于是并发操作下才
会
出现
死锁
,考虑到有可能是两个接口当中的业务更新sql有交叉的可能,导致了互相竞争锁资源引起
死锁
问题
解决
方案;分析两个业务的所有sql及执行顺序,找出交叉...
1、并发下锁的问题:其实这有两个问题,第一并发下数据的脏读脏写,第二就是防止并发下导致为了防止脏读脏写的而
产生
的其他问题(例如
死锁
)。
这里不再阐述相关的锁机制,我只说明项目中使用的锁以及遇到的问题。
库存
中心这里我使用了三种机制:悲观锁、乐观锁、数据库CAS操作。
个人认为悲观锁、乐观锁最终还是在代码逻辑层面去控制数据读写,悲观锁实现简单,但是坑多,乐观锁实现稍微复杂,效率也较高。CAS则...