广告
返回顶部
首页 > 资讯 > 数据库 >MySQL死锁如何解决
  • 1016
分享到

MySQL死锁如何解决

2024-04-02 19:04:59 1016人浏览 独家记忆
摘要

Mysql死锁如何解决,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。环境准备数据库隔离级别:  mysql>&n

Mysql如何解决,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。

环境准备

数据库隔离级别:

  mysql> select @@tx_isolation;   +-----------------+   | @@tx_isolation  |   +-----------------+   | REPEATABLE-READ |   +-----------------+   1 row in set, 1 warning (0.00 sec)

自动提交关闭:

  mysql> set autocommit=0;   Query OK, 0 rows affected (0.00 sec)      mysql> select @@autocommit;   +--------------+   | @@autocommit |   +--------------+   |            0 |   +--------------+   1 row in set (0.00 sec)

表结构:

  //id是自增主键,name是非唯一索引,balance普通字段   CREATE TABLE `account` (    `id` int(11) NOT NULL AUTO_INCREMENT,     `name` varchar(255) DEFAULT NULL,     `balance` int(11) DEFAULT NULL,     PRIMARY KEY (`id`),     KEY `idx_name` (`name`) USING BTREE   ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

表中的数据:

MySQL死锁如何解决

模拟并发

开启两个终端模拟事务并发情况,执行顺序以及实验现象如下:

MySQL死锁如何解决

1)事务A执行更新操作,更新成功

mysql> update account set balance =1000 where name ='Wei'; Query OK, 1 row affected (0.01 sec)

2)事务B执行更新操作,更新成功

mysql> update account set balance =1000 where name ='Eason';  Query OK, 1 row affected (0.01 sec)

3)事务A执行插入操作,陷入阻塞~

mysql> insert into account values(null,'Jay',100);

MySQL死锁如何解决


这时候可以用

select*frominfORMation_schema.innodb_locks;

查看锁情况:

MySQL死锁如何解决

4)事务B执行插入操作,插入成功,同时事务A的插入由阻塞变为死锁error。

mysql> insert into account values(null,'Yan',100);  Query OK, 1 row affected (0.01 sec)

MySQL死锁如何解决

锁介绍

在分析死锁日志前,先做一下锁介绍,哈哈~

MySQL死锁如何解决

主要介绍一下兼容性以及锁模式类型的锁:

共享锁与排他锁

InnoDB 实现了标准的行级锁,包括两种:共享锁(简称 s 锁)、排它锁(简称 x 锁)。

  • 共享锁(S锁):允许持锁事务读取一行。

  • 排他锁(X锁):允许持锁事务更新或者删除一行。

如果事务 T1 持有行 r 的 s 锁,那么另一个事务 T2 请求 r 的锁时,会做如下处理:

  • T2 请求 s 锁立即被允许,结果 T1 T2 都持有 r 行的 s 锁

  • T2 请求 x 锁不能被立即允许

如果 T1 持有 r 的 x 锁,那么 T2 请求 r 的 x、s 锁都不能被立即允许,T2 必须等待T1释放 x  锁才可以,因为X锁与任何的锁都不兼容。

MySQL死锁如何解决

意向锁

  • 意向共享锁( IS 锁):事务想要获得一张表中某几行的共享锁

  • 意向排他锁( IX 锁):事务想要获得一张表中某几行的排他锁

比如:事务1在表1上加了S锁后,事务2想要更改某行记录,需要添加IX锁,由于不兼容,所以需要等待S锁释放;如果事务1在表1上加了IS锁,事务2添加的IX锁与IS锁兼容,就可以操作,这就实现了更细粒度的加锁。

InnoDB存储引擎中锁的兼容性如下表:

MySQL死锁如何解决

记录锁(Record Locks)

  • 记录锁是最简单的行锁,仅仅锁住一行。如: SELECT c1 FROM t WHERE c1=10FOR  UPDATE

  • 记录锁永远都是加在索引上的,即使一个表没有索引,InnoDB也会隐式的创建一个索引,并使用这个索引实施记录锁。

  • 会阻塞其他事务对其插入、更新、删除

记录锁的事务数据(关键词:lock_mode X locks rec butnotgap),记录如下:

  RECORD LOCKS space id 58 page no 3 n bits 72 index `PRIMARY` of table `test`.`t`    trx id 10078 lock_mode X locks rec but not gap   Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 0    0: len 4; hex 8000000a; asc     ;;    1: len 6; hex 00000000274f; asc     'O;;    2: len 7; hex b60000019d0110; asc        ;;

间隙锁(Gap Locks)

  • 间隙锁是一种加在两个索引之间的锁,或者加在第一个索引之前,或最后一个索引之后的间隙。

  • 使用间隙锁锁住的是一个区间,而不仅仅是这个区间中的每一条数据。

  • 间隙锁只阻止其他事务插入到间隙中,他们不阻止其他事务在同一个间隙上获得间隙锁,所以 gap x lock 和 gap s lock 有相同的作用。

间隙锁的事务数据(关键词:gap before rec),记录如下:

  RECORD LOCKS space id 177 page no 4 n bits 80 index idx_name of table `test2`.`account`    trx id 38049 lock_mode X locks gap before rec   Record lock, heap no 6 PHYSICAL RECORD: n_fields 2; compact format; info bits 0    0: len 3; hex 576569; asc Wei;;    1: len 4; hex 80000002; asc     ;;

Next-Key Locks

  • Next-key锁是记录锁和间隙锁的组合,它指的是加在某条记录以及这条记录前面间隙上的锁。

插入意向锁(Insert Intention)

  • 插入意向锁是在插入一行记录操作之前设置的一种间隙锁,这个锁释放了一种插入方式的信号,亦即多个事务在相同的索引间隙插入时如果不是插入间隙中相同的位置就不需要互相等待。

  • 假设有索引值4、7,几个不同的事务准备插入5、6,每个锁都在获得插入行的独占锁之前用插入意向锁各自锁住了4、7之间的间隙,但是不阻塞对方因为插入行不冲突。

事务数据类似于下面:

  RECORD LOCKS space id 31 page no 3 n bits 72 index `PRIMARY` of table `test`.`child`   trx id 8731 lock_mode X locks gap before rec insert intention waiting   Record lock, heap no 3 PHYSICAL RECORD: n_fields 3; compact format; info bits 0    0: len 4; hex 80000066; asc    f;;    1: len 6; hex 000000002215; asc     " ;;    2: len 7; hex 9000000172011c; asc     r  ;;...

锁模式兼容矩阵(横向是已持有锁,纵向是正在请求的锁):

MySQL死锁如何解决

如何读懂死锁日志?

show engine innodb status

可以用 show engine innodb status,查看最近一次死锁日志哈~,执行后,死锁日志如下:

  0x243c   *** (1) TRANSACTION:   TRANSACTION 38048, ACTIVE 92 sec inserting   mysql tables in use 1, locked 1   LOCK WAIT 4 lock struct(s), heap size 1136, 4 row lock(s), undo log entries 2   MySQL thread id 53, OS thread handle 2300, query id 2362 localhost ::1 root update   insert into account values(null,'Jay',100)   *** (1) WAITING FOR THIS LOCK TO BE GRANTED:   RECORD LOCKS space id 177 page no 4 n bits 80 index idx_name of table `test2`.`account`   trx id 38048 lock_mode X locks gap before rec insert intention waiting  Record lock, heap no 6 PHYSICAL RECORD: n_fields 2; compact format; info bits 0   0: len 3; hex 576569; asc Wei;;   1: len 4; hex 80000002; asc     ;;    *** (2) TRANSACTION:  TRANSACTION 38049, ACTIVE 72 sec inserting, thread declared inside InnoDB 5000  mysql tables in use 1, locked 1  5 lock struct(s), heap size 1136, 4 row lock(s), undo log entries 2  MySQL thread id 52, OS thread handle 9276, query id 2363 localhost ::1 root update  insert into account  values(null,'Yan',100)  *** (2) HOLDS THE LOCK(S):  RECORD LOCKS space id 177 page no 4 n bits 80 index idx_name of table `test2`.`account`   trx id 38049 lock_mode X locks gap before rec  Record lock, heap no 6 PHYSICAL RECORD: n_fields 2; compact format; info bits 0   0: len 3; hex 576569; asc Wei;;   1: len 4; hex 80000002; asc     ;;    *** (2) WAITING FOR THIS LOCK TO BE GRANTED:  RECORD LOCKS space id 177 page no 4 n bits 80 index idx_name of table `test2`.`account`   trx id 38049 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 (1)

我们如何分析以上死锁日志呢?

第一部分

1)找到关键词TRANSACTION,事务38048

MySQL死锁如何解决

2)查看正在执行的SQL

insert into account values(null,'Jay',100)

3)正在等待锁释放(WAITING FOR THIS LOCK TO BE GRANTED),插入意向排他锁(lockmode X locks gap  before rec insert intention waiting),普通索引(idxname),物理记录(PHYSICAL  RECORD),间隙区间(未知,Wei);

MySQL死锁如何解决

第二部分

1)找到关键词TRANSACTION,事务38049

MySQL死锁如何解决

2)查看正在执行的SQL

insert into account values(null,'Yan',100)

3)持有锁(HOLDS THE LOCK),间隙锁(lockmode X locks gap before rec),普通索引(index  idxname),物理记录(physical record),区间(未知,Wei);

MySQL死锁如何解决

4)正在等待锁释放(waiting for this lock to be granted),插入意向锁(lockmode X insert  intention waiting),普通索引上(index idxname),物理记录(physical record),间隙区间(未知,+∞);

MySQL死锁如何解决

5)事务1回滚(we roll back transaction 1);

查看日志结果

MySQL死锁如何解决

查看日志可得:

  • 事务A正在等待的插入意向排他锁(事务A即日志的事务1,根据insert语句来对号入座的哈),正在事务B的怀里~

  • 事务B持有间隙锁,正在等待插入意向排它锁

这里面,有些朋友可能有疑惑,

  • 事务A持有什么锁呢?日志根本看不出来。它又想拿什么样的插入意向排他锁呢?

  • 事务B拿了具体什么的间隙锁呢?它为什么也要拿插入意向锁?

  • 死锁的死循环是怎么形成的?目前日志看不出死循环构成呢?

我们接下来一小节详细分析一波,一个一个问题来~

死锁分析

死锁死循环四要素

MySQL死锁如何解决

  • 互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。

  • 请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。

  • 不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。

  • 环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。

事务A持有什么锁呢?它又想拿什么样的插入意向排他锁呢?

为了方便记录,例子用W表示Wei,J表示Jay,E表示Eason哈~

我们先来分析事务A中update语句的加锁情况~

update account set balance =1000 where name ='Wei';

间隙锁:

  • Update语句会在非唯一索引的name加上左区间的间隙锁,右区间的间隙锁(因为目前表中只有name='Wei'的一条记录,所以没有中间的间隙锁~),即(E,W)  和(W,+∞)

  • 为什么存在间隙锁?因为这是RR的数据库隔离级别,用来解决幻读问题用的~

记录锁

  • 因为name是索引,所以该update语句肯定会加上W的记录锁

Next-Key锁

  • Next-Key锁=记录锁+间隙锁,所以该update语句就有了(E,W]的 Next-Key锁

综上所述,事务A执行完update更新语句,会持有锁:

  • Next-key Lock:(E,W]

  • Gap Lock :(W,+∞)

我们再来分析一波事务A中insert语句的加锁情况

insert into account values(null,'Jay',100);

间隙锁:

  • 因为Jay(J在E和W之间),所以需要请求加(E,W)的间隙锁

插入意向锁(Insert Intention)

  • 插入意向锁是在插入一行记录操作之前设置的一种间隙锁,这个锁释放了一种插入方式的信号,即事务A需要插入意向锁(E,W)

因此,事务A的update语句和insert语句执行完,它是持有了 (E,W]的 Next-Key锁,(W,+∞)的Gap锁,想拿到  (E,W)的插入意向排它锁,等待的锁跟死锁日志是对上的,哈哈~

MySQL死锁如何解决

事务B拥有了什么间隙锁?它为什么也要拿插入意向锁?

同理,我们再来分析一波事务B,update语句的加锁分析:

update account set balance =1000 where name ='Eason';

间隙锁:

  • Update语句会在非唯一索引的name加上左区间的间隙锁,右区间的间隙锁(因为目前表中只有name='Eason'的一条记录,所以没有中间的间隙锁~),即(-∞,E)和(E,W)

记录锁

  • 因为name是索引,所以该update语句肯定会加上E的记录锁

Next-Key锁

  • Next-Key锁=记录锁+间隙锁,所以该Update语句就有了(-∞,E]的 Next-Key锁

综上所述,事务B执行完update更新语句,会持有锁:

  • Next-key Lock:(-∞,E]

  • Gap Lock :(E,W)

我们再来分析一波B中insert语句的加锁情况

insert into account values(null,'Yan',100);

间隙锁:

  • 因为Yan(Y在W之后),所以需要请求加(W,+∞)的间隙锁

插入意向锁(Insert Intention)

  • 插入意向锁是在插入一行记录操作之前设置的一种间隙锁,这个锁释放了一种插入方式的信号,即事务A需要插入意向锁(W,+∞)

所以,事务B的update语句和insert语句执行完,它是持有了 (-∞,E]的 Next-Key锁,(E,W)的Gap锁,想拿到  (W,+∞)的间隙锁,即插入意向排它锁,加锁情况跟死锁日志也是对上的~

MySQL死锁如何解决

MySQL死锁如何解决

死锁真相还原

接下来呢,让我们一起还原死锁真相吧~哈哈~

MySQL死锁如何解决

  • 事务A执行完Update Wei的语句,持有(E,W]的Next-key Lock,(W,+∞)的Gap Lock ,插入成功~

  • 事务B执行完Update Eason语句,持有(-∞,E]的 Next-Key Lock,(E,W)的Gap Lock,插入成功~

  • 事务A执行Insert Jay的语句时,因为需要(E,W)的插入意向锁,但是(E,W)在事务B怀里,所以它陷入心塞~

  • 事务B执行Insert Yan的语句时,因为需要(W,+∞) 的插入意向锁,但是(W,+∞) 在事务A怀里,所以它也陷入心塞。

  • 事务A持有(W,+∞)的Gap Lock,在等待(E,W)的插入意向锁,事务B持有(E,W)的Gap锁,在等待(W,+∞)  的插入意向锁,所以形成了死锁的闭环~(Gap锁与插入意向锁会冲突的,可以看回锁介绍的锁模式兼容矩阵哈~)

  • 事务A,B形成了死锁闭环后,因为Innodb的底层机制,它会让其中一个事务让出资源,另外的事务执行成功,这就是为什么你最后看到事务B插入成功了,但是事务A的插入显示了Deadlock  found ~

关于MySQL死锁如何解决问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注编程网数据库频道了解更多相关知识。

您可能感兴趣的文档:

--结束END--

本文标题: MySQL死锁如何解决

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

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

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • MySQL死锁如何解决
    MySQL死锁如何解决,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。环境准备数据库隔离级别:  mysql>&n...
    99+
    2022-10-18
  • Mysql如何解决死锁问题
    这篇文章主要为大家展示了“Mysql如何解决死锁问题”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Mysql如何解决死锁问题”这篇文章吧。 ...
    99+
    2022-10-19
  • 如何解决MySQL死锁问题
    这篇文章主要介绍“如何解决MySQL死锁问题”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“如何解决MySQL死锁问题”文章能帮助大家解决问题。1、什么是死锁死锁是并...
    99+
    2022-10-19
  • mysql出现死锁如何解决
    mysql出现死锁的解决方法打开mysql服务器监控,终止系统中的一个或多个死锁进程,直至打破循环环路,使系统从死锁状态中解除出来。通过在表上建立一个聚集索引,实现解决死锁;从一个或多个进程中抢占足够数量的资源,分配给死锁进程,以打破死锁状...
    99+
    2022-10-09
  • 解决MySQL死锁的方法
    下面一起来了解下解决MySQL死锁的方法,相信大家看完肯定会受益匪浅,文字在精不在多,希望解决MySQL死锁的方法这篇短内容是你想要的。 一、查看MySQL死锁MySQL数据库会自己解决死锁,ki...
    99+
    2022-10-18
  • mysql死锁的解决方法
    mysql死锁的解决方法?这个问题可能是我们日常学习或工作经常见到的。希望通过这个问题能让你收获颇深。下面是小编给大家带来的参考内容,让我们一起来看看吧!MySQL有两种死锁处理方式:● 等待,直到超时(i...
    99+
    2022-10-18
  • redis如何解决死锁
    redis解决死锁的方法:从其它进程剥夺足够数量的资源给死锁进程,解除死锁状态。撤消死锁进程或撤消代价最小的进程,直至有足够的资源可用。...
    99+
    2022-10-18
  • 【mysql】mysql死锁问题解决方案
    mysql死锁问题解决方案 查询出是被哪个进程给锁住了为什么会产生死锁日志内容:日志解析:找到问题: 解决方案 查询出是被哪个进程给锁住了 执行sql: select ...
    99+
    2023-09-23
    mysql adb 数据库
  • mysql死锁介绍以及解决
    什么是死锁 死锁是2+个线程在执行过程中, 因争夺资源而造成的相互等待的现象,若无外力作用,它们将无法推进下去。 死锁产生的4个必要条件 互斥条件 指进程对所分配的资源进行排他性使用,即一段时间内某资源只有一个进程占用,其他的进程请求资源只...
    99+
    2023-08-17
    mysql java 微服务
  • mysql kill process解决死锁问题
    目录mysql kill process解决死锁mysql死锁异常分析及解决问题产生原因分析解决方案mysql kill process解决死锁 1、查看进程列表, 找到ID show processlist; +--...
    99+
    2022-08-24
  • 怎样解决Mysql死锁问题
    怎样解决Mysql死锁问题,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。 show engine in...
    99+
    2022-10-18
  • mysql死锁怎么排查及解决
    MySQL死锁是指两个或多个事务互相持有对方需要的资源,同时又等待对方释放资源,导致系统无法继续进行下去的情况。解决MySQL死锁问...
    99+
    2023-09-21
    mysql
  • Mysql如何使用kill命令解决死锁问题
    这篇文章给大家介绍Mysql如何使用kill命令解决死锁问题,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。在使用mysql运行某些语句时,会因数据量太大而导致死锁,没有反映。这个时候,...
    99+
    2022-10-18
  • 如何解决MySQL的RR模式下死锁一列
    如何解决MySQL的RR模式下死锁一列,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。环境:版本5.7.29 RR隔离级别一、案例模拟CRE...
    99+
    2022-10-18
  • MySQL - 死锁的产生及解决方案
    MySQL - 死锁的产生及解决方案 1. 死锁与产生死锁的四个必要条件1.1 什么是死锁1.2 死锁产生的4个必要条件 2. 死锁案例2.1 表锁死锁2.2 行锁死锁2.3 共享锁转换为排他锁 3. 死锁排查4. 实例分析...
    99+
    2023-08-17
    mysql 数据库
  • MySQL死锁的原因及解决方法
    这篇文章主要介绍“MySQL死锁的原因及解决方法”,在日常操作中,相信很多人在MySQL死锁的原因及解决方法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”MySQL死锁的原因...
    99+
    2022-10-18
  • PostgreSQL出现死锁该如何解决
    目录什么是数据库死锁定位死锁死锁可能原因及解决办法1、索引使用不当导致的死锁问题2、不同事务之间的访问顺序问题避免死锁的建议附:数据库中常见的死锁原因与解决方案总结什么是数据库死锁 ...
    99+
    2022-11-13
  • java多线程死锁如何解决
    Java中死锁的解决办法有以下几种:1. 避免使用多个锁:当多个线程需要获取多个锁时,可以尝试将多个锁合并为一个锁,或者将一个锁拆分...
    99+
    2023-08-24
    java
  • RC级别下MySQL死锁问题的解决
    目录背景死锁分析死锁解决背景 在工作中碰到一次死锁问题,业务背景是在mq接收商品主数据时会更新商品其他数据,由于商品主数据和商品其他信息是一对多的关系,所以采用先删后增的方式,结果异...
    99+
    2022-11-13
  • mysql中的死锁是什么?怎么解决
    这篇文章将为大家详细讲解有关mysql中的死锁以及解决方法,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。死锁是什么所谓死锁:是指两个或两个以上的进程在执行过程中,因争夺资...
    99+
    2022-10-18
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作