返回顶部
首页 > 资讯 > 数据库 >Mysql并发插入死锁问题
  • 951
分享到

Mysql并发插入死锁问题

mysql数据库sql死锁 2023-10-10 06:10:00 951人浏览 八月长安
摘要

文章目录 一、问题二、复现表结构执行顺序死锁信息 三、死锁原因四、修改代码FA&QReference 一、问题 线上数据库版本,隔离级别:5.6.36-log,REPEA

文章目录

一、问题

线上数据库版本,隔离级别:5.6.36-log,REPEATABLE-READ

SELECT @@tx_isolation,version();SHOW VARIABLES;SHOW ENGINE INNODB STATUS;SELECT * FROM `perfORMance_schema`.data_locks;SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

项目遇到死,业务代码大概如下:

@TransactionalmethodA() {    updateTableA;    methodB();    return true;}@TransactionalmethodB() {    try {        select * from test_lock where uid = 1 and anchor = 1 for update        // insert or update        insert into test_lock(uid, anchor, num) values(1, 1, 1)    } catch {        log.error("deadlock rollback")    }}

上诉代码,当同一个用户同时添加两个不存在的记录时,有可能死锁。当报错后,捕获异常没有抛出,这时方法A相对于调用方来说是成功执行。

二、复现

表结构
CREATE TABLE `test_lock` (  `id` int NOT NULL AUTO_INCREMENT,  `uid` int NOT NULL,  `anchor` int NOT NULL,  `num` int NOT NULL,  PRIMARY KEY (`id`),  UNIQUE KEY `uid_anchor` (`uid`,`anchor`) USING BTREE) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8mb3;
执行顺序
事务1事务2结果
BEGIN;
SELECT * FROM test_lock WHERE uid = 1 and anchor = 1 FOR UPDATE;
事务1加锁
BEGIN;
SELECT * FROM test_lock WHERE uid = 1 and anchor = 2 FOR UPDATE;
事务2加锁
INSERT INTO test_lock (uid, anchor, num) VALUES (1, 1, 1);事务1插入数据
INSERT INTO test_lock (uid, anchor, num) VALUES (1, 2, 1);事务2插入数据,此时报死锁
死锁信息
    ------------------------    LATEST DETECTED DEADLOCK    ------------------------    2023-05-15 15:03:45 139836002379520    *** (1) TRANSACTION:    TRANSACTION 259310840, ACTIVE 95 sec inserting    Mysql tables in use 1, locked 1    LOCK WaiT 3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1    mysql thread id 100802292, OS thread handle 139832517502720, query id 1989879086 10.254.137.152 pepper_activity update    INSERT INTO test_lock (uid, anchor, num) VALUES (1, 1, 1)        *** (1) HOLDS THE LOCK(S):    RECORD LOCKS space id 13103 page no 5 n bits 72 index uid_anchor of table `payment_ext`.`test_lock` trx id 259310840 lock_mode X    Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0     0: len 8; hex 73757072656d756d; asc supremum;;*** (1) WAITING FOR THIS LOCK TO BE GRANTED:    RECORD LOCKS space id 13103 page no 5 n bits 72 index uid_anchor of table `payment_ext`.`test_lock` trx id 259310840 lock_mode X insert intention waiting    Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0     0: len 8; hex 73757072656d756d; asc supremum;;*** (2) TRANSACTION:    TRANSACTION 259311033, ACTIVE 89 sec inserting    mysql tables in use 1, locked 1    LOCK WAIT 3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1    MySQL thread id 100810550, OS thread handle 139842288764672, query id 1989880897 10.254.137.152 pepper_activity update    INSERT INTO test_lock (uid, anchor, num) VALUES (1, 2, 1)        *** (2) HOLDS THE LOCK(S):    RECORD LOCKS space id 13103 page no 5 n bits 72 index uid_anchor of table `payment_ext`.`test_lock` trx id 259311033 lock_mode X    Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0     0: len 8; hex 73757072656d756d; asc supremum;;*** (2) WAITING FOR THIS LOCK TO BE GRANTED:    RECORD LOCKS space id 13103 page no 5 n bits 72 index uid_anchor of table `payment_ext`.`test_lock` trx id 259311033 lock_mode X insert intention waiting    Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0     0: len 8; hex 73757072656d756d; asc supremum;;        *** WE ROLL BACK TRANSACTION (2)    

三、死锁原因

分析死锁日志,看TRANSACTION (1)和(2),正在HOLDS和WAITING的锁。要插入的数据都不存在,事务1和事务2的select … for update分别加了一个间隙锁,然后插入数据之前要获取插入意向锁。因为间隙锁和意向锁互斥,所以造成了互相等待最终导致了死锁。

间隙锁:间隙锁是在索引记录之间的间隙上的锁,或者是第一条记录之前或最后一条记录后的间隙上的锁。可以防止操作过程中其他事务插入间隙。间隙锁可以共存,一个事务获取的间隙锁不会阻止另一个事务在同一间隙上获取间隙锁。

插入意向锁:插入意向锁是一种 INSERT 在行插入之前设置的间隙锁。这个锁表示插入的意图,这样插入到同一个索引间隙中的多个事务如果没有插入到间隙中的相同位置,则不需要相互等待。比如有1和5两条记录,两个事务分别插入2和3,插入之前都会使用插入意向锁锁定1-5的间隙,但是因为是不同的行,所以不需要互相等待。

所以,间隙锁之间可以共存,插入意向锁之间可以共存,但是间隙锁和插入意向锁互斥。

for update的用处,第一是对记录加X锁,第二是可以当前读,也就是在可重复读隔离级别下,可以读到其他事务已提交的数据。

四、修改代码

  1. 将插入之前的间隙锁去除(select…for update),修改时使用自增修改道具num=num+1,在方法上使用Redis分布式锁代替数据库锁(添加,扣减)
  2. 将异常抛出
  3. 插入统计数据的时候,异步做,不影响主流程
  4. 设置spring事务传播类型为REQUIRES_NEW

不要大事务,锁定数据多,时间长,死锁概率就会更大

业务上使用功能分布式锁限制并发修改,防止死锁

FA&Q

验证:分别在两个间隙执行会有阻塞吗?
结果:不会阻塞,插入意向锁是一个特殊的间隙锁。

验证:select … for update 不存在数据的时候,加的锁是间隙锁吗?存在数据时是行锁吗?
结果:存在数据时为行锁,不存在数据时为间隙锁

验证:间隙锁之间不会互斥,插入意向锁之间不会互斥。
结果:同一个事务的间隙锁和插入意向锁不会互斥,两个事务之间的间隙锁和插入意向锁会互斥。

验证:间隙锁在READ COMMITTED隔离级别是否启用?
结果:不启用。

验证:当前读和快照读?
结果:可重复读隔离级别下,事务内普通查询是快照读,select … for update 和 select … lock in share mode 是当前读。

验证:Mysql死锁回滚是全部回滚而不是回滚到上个还原点。
结果:全部回滚。

验证:首先update,失败时进行插入
结果:同样是死锁

验证:on duplicate key update插入两条会死锁吗?
结果:本地执行没发现报错,但是他的执行原理和 select … for update然后插入,是同样的原理。所以高并发下依然有问题。

Reference

Mysql锁

来源地址:https://blog.csdn.net/GY325416/article/details/130712382

您可能感兴趣的文档:

--结束END--

本文标题: Mysql并发插入死锁问题

本文链接: https://www.lsjlt.com/news/426716.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Mysql并发插入死锁问题
    文章目录 一、问题二、复现表结构执行顺序死锁信息 三、死锁原因四、修改代码FA&QReference 一、问题 线上数据库版本,隔离级别:5.6.36-log,REPEA...
    99+
    2023-10-10
    mysql 数据库 sql 死锁
  • mysql中如何排查并发插入引起的死锁问题
    小编给大家分享一下mysql中如何排查并发插入引起的死锁问题,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!挂着VPN排查问题,不...
    99+
    2024-04-02
  • Java 内存模型与死锁:深入理解并发编程中的死锁问题
    Java 内存模型(JMM)是一套规范,它定义了 Java 程序中变量是如何在多个线程之间共享的。JMM 规定了线程如何从主内存中读取和写入变量,以及如何将变量的值存储到主内存中。 死锁是并发编程中常见的一种问题,它发生在两个或多个线程...
    99+
    2024-02-04
    Java 内存模型 死锁 并发编程 同步 等待 通知 中断
  • MySQL——插入加锁/唯一索引插入死锁/批量插入效率
    本篇主要介绍MySQL跟加锁相关的一些概念、MySQL执行插入Insert时的加锁过程、唯一索引下批量插入可能导致的死锁情况,以及分别从业务角度和MySQL配置角度介绍提升批量插入的效率的方法; MySQL跟加锁相关的一些概念 在介...
    99+
    2023-08-31
    mysql 加锁 批量插入 唯一索引 S锁/X锁 Powered by 金山文档
  • 关于MySQL死锁问题的深入分析
    前言 如果我们的业务处在一个非常初级的阶段,并发程度比较低,那么我们可以几年都遇不到一次死锁问题的发生,反之,我们业务的并发程度非常高,那么时不时爆出的死锁问题肯定让我们非常挠头。不过在死锁问题发生时,很多...
    99+
    2024-04-02
  • MySQL锁等待与死锁问题分析
    前言:  在 MySQL 运维过程中,锁等待和死锁问题是令各位 DBA 及开发同学非常头痛的事。出现此类问题会造成业务回滚、卡顿等故障,特别是业务繁忙的系统,出现死锁问题后影响会更严重。本篇文章我们一起来学...
    99+
    2022-05-22
    MySQL 锁等待 MySQL 死锁
  • 【mysql】mysql死锁问题解决方案
    mysql死锁问题解决方案 查询出是被哪个进程给锁住了为什么会产生死锁日志内容:日志解析:找到问题: 解决方案 查询出是被哪个进程给锁住了 执行sql: select ...
    99+
    2023-09-23
    mysql adb 数据库
  • log4j2的高并发死锁问题配置如何优化
    这篇文章给大家分享的是有关log4j2的高并发死锁问题配置如何优化的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。log4j2高并发死锁问题配置优化Maven中pom.xml引用<log4j2.version...
    99+
    2023-06-22
  • log4j2的高并发死锁问题配置优化方式
    目录log4j2高并发死锁问题配置优化Maven中pom.xml引用配置如下log4j2.x简单使用文档1.项目中引入两个jar包2.指定日志配置文件位置3.简单的配置文件4.获取L...
    99+
    2024-04-02
  • C#开发中如何处理并发编程和死锁问题
    C#开发中如何处理并发编程和死锁问题,需要具体代码示例摘要:并发编程是现代软件开发中的重要主题,但也带来了一些挑战,例如线程安全、竞态条件和死锁等问题。本文将重点讨论在C#开发中处理并发编程和死锁问题的一些方法,并给出具体的代码示例。引言:...
    99+
    2023-10-22
    并发编程 (Concurrency Programming) 死锁问题 (Deadlock problem) 处理方法
  • 怎样解决Mysql死锁问题
    怎样解决Mysql死锁问题,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。 show engine in...
    99+
    2024-04-02
  • 如何处理MySQL死锁问题
    小编给大家分享一下如何处理MySQL死锁问题,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧! MySQL里的锁兼容列表大体是这样...
    99+
    2024-04-02
  • Mysql如何解决死锁问题
    这篇文章主要为大家展示了“Mysql如何解决死锁问题”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Mysql如何解决死锁问题”这篇文章吧。 ...
    99+
    2024-04-02
  • 如何解决MySQL死锁问题
    这篇文章主要介绍“如何解决MySQL死锁问题”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“如何解决MySQL死锁问题”文章能帮助大家解决问题。1、什么是死锁死锁是并...
    99+
    2024-04-02
  • redis发生死锁问题怎么办
    这篇文章主要介绍了redis发生死锁问题怎么办,具有一定借鉴价值,需要的朋友可以参考下。希望大家阅读完这篇文章后大有收获。下面让小编带着大家一起了解一下。就分布式锁而言,一个常用的问题就是如果一个服务set...
    99+
    2024-04-02
  • 如何深入解析mssql在高频高并发访问时键查找死锁问题
    如何深入解析mssql在高频高并发访问时键查找死锁问题,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。死锁对于DBA或是数据库开发人员而言并不陌...
    99+
    2024-04-02
  • 高并发状态下ReplaceInto造成的死锁问题解决
    目录1.问题出现:2.分析解决3.解决方案:1.问题出现: 在测试阶段,大数据并发的情况下,发现sql语句造成表的死锁,过一段时间,死锁消失。于是进行排查 报错如下: 对应的sql...
    99+
    2023-01-18
    Replace Into死锁 Replace Into
  • C++并发编程:如何识别和解决死锁问题?
    在 c++++ 并发编程中,死锁问题发生在一或多个线程无限期等待其他线程释放资源时,导致程序挂起。我们可以使用 std::lock_guard 和 std::unique_lock 实现...
    99+
    2024-05-04
    c++ 死锁问题
  • 死锁问题详解
    目录前言资源可抢占资源和不可抢占资源资源获取死锁资源死锁的条件死锁模型鸵鸟算法死锁检测和恢复从死锁中恢复通过抢占进行恢复通过回滚进行恢复杀死进程恢复死锁避免单个资源的银行家算法破坏死...
    99+
    2024-04-02
  • 怎么理解MySQL wwwhj8828coml8o88O49999死锁问题
    本篇内容介绍了“怎么理解MySQL wwwhj8828coml8o88O49999死锁问题”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作