Exploring
首页
  • Java

    • 面向对象的思想OOP
    • 浅谈Java反射原理
    • endorsed覆盖JDK中的类
  • 认证与授权

    • LDAP概念和原理介绍
    • OAuth2介绍
  • Impala

    • Impala 介绍
  • MySQL

    • 关于MySQL的一些面试题
    • 解决MySQL不到中文数据
    • 数据库之事务与实现原理
  • Oracle

    • oracle的表空间,用户管理,表操作,函数
    • oracle的查询、视图、索引
    • plsql简单入门
  • Redis

    • 数据类型详解
    • 跳越表
    • 数据持久化的两种方式
  • 共识算法

    • gossip
  • RPC

    • GRPC初识与快速入门
    • ProtocolBuffer基本语法
  • RabbitMQ

    • RabbitMQ入门程序之HelloWorld
    • RabbitMQ之工作模式
  • Zookeeper

    • Zookeeper一文入门
  • Docker

    • Docker入门初体验
  • Maven

    • 把自己的包到Maven中央仓库
    • Maven之自定义插件
  • Nginx

    • nginx的安装
    • nginx的配置文件
    • nignx 的变量
  • Tomcat

    • Servlet3通过SPI进行注册组件
  • Vagrant

    • vagrant 初始化
    • vagrant 常用配置
    • vagrant 自己制作 box
  • Linux

    • 启动方式 Systemd
    • 后台服务
    • 防火墙与 Iptables
  • 设计模式

    • 设计模式-代理
    • 设计模式-单例模式
    • 设计模式-迭代器
  • 分布式

    • CAP 理论
  • 数据结构

    • 数据结构之堆Heap
    • 数据结构之哈希表
    • 数据结构之队列
  • 计算机网络

    • HTTP与HTTPS详解
    • 浅谈DNS协议
    • ISP中的网络层
  • 算法

    • 常用查找算法及Java实现
    • 常用排序算法及Java实现
    • 迪杰斯特拉算法
  • 操作系统

    • 操作系统之进程调度算法
    • 操作系统之进程通讯IPC
    • 操作系统之内存管理
  • 抓包

    • 生成安卓系统证书
  • 加解密

    • 常见加密算法
    • 公开秘钥基础知识
    • RSA 解析
  • Windows

    • scoop 包管理
    • windows-terminal 配置
    • 增强 PowerShell
归档
Github (opens new window)
首页
  • Java

    • 面向对象的思想OOP
    • 浅谈Java反射原理
    • endorsed覆盖JDK中的类
  • 认证与授权

    • LDAP概念和原理介绍
    • OAuth2介绍
  • Impala

    • Impala 介绍
  • MySQL

    • 关于MySQL的一些面试题
    • 解决MySQL不到中文数据
    • 数据库之事务与实现原理
  • Oracle

    • oracle的表空间,用户管理,表操作,函数
    • oracle的查询、视图、索引
    • plsql简单入门
  • Redis

    • 数据类型详解
    • 跳越表
    • 数据持久化的两种方式
  • 共识算法

    • gossip
  • RPC

    • GRPC初识与快速入门
    • ProtocolBuffer基本语法
  • RabbitMQ

    • RabbitMQ入门程序之HelloWorld
    • RabbitMQ之工作模式
  • Zookeeper

    • Zookeeper一文入门
  • Docker

    • Docker入门初体验
  • Maven

    • 把自己的包到Maven中央仓库
    • Maven之自定义插件
  • Nginx

    • nginx的安装
    • nginx的配置文件
    • nignx 的变量
  • Tomcat

    • Servlet3通过SPI进行注册组件
  • Vagrant

    • vagrant 初始化
    • vagrant 常用配置
    • vagrant 自己制作 box
  • Linux

    • 启动方式 Systemd
    • 后台服务
    • 防火墙与 Iptables
  • 设计模式

    • 设计模式-代理
    • 设计模式-单例模式
    • 设计模式-迭代器
  • 分布式

    • CAP 理论
  • 数据结构

    • 数据结构之堆Heap
    • 数据结构之哈希表
    • 数据结构之队列
  • 计算机网络

    • HTTP与HTTPS详解
    • 浅谈DNS协议
    • ISP中的网络层
  • 算法

    • 常用查找算法及Java实现
    • 常用排序算法及Java实现
    • 迪杰斯特拉算法
  • 操作系统

    • 操作系统之进程调度算法
    • 操作系统之进程通讯IPC
    • 操作系统之内存管理
  • 抓包

    • 生成安卓系统证书
  • 加解密

    • 常见加密算法
    • 公开秘钥基础知识
    • RSA 解析
  • Windows

    • scoop 包管理
    • windows-terminal 配置
    • 增强 PowerShell
归档
Github (opens new window)
  • MySQL

    • 关于MySQL的一些面试题
    • 解决MySQL不到中文数据
    • 数据库之事务与实现原理
    • MyISAM和InnoDB引擎区别
    • MySQL不同隔离级别下的加锁情况
    • MySql常用指令集
    • MySQL的索引
    • MySQL的字符集与校对规则
    • MySQL调优利器Explain
    • MySQL死锁的调试
      • 什么是死锁?
      • 死锁例子
      • 死锁检测机制
      • 处理死锁
        • 查找死锁
        • 定位死锁
      • 参考
    • MySQL之Gap-Locks与Next-key-Locks
    • SQL之组内排序
  • Oracle

  • Redis

  • 数据库
  • MySQL
unclezs
2020-08-18
0
目录

MySQL死锁的调试

# 什么是死锁?

死锁是指由于每个事务都持有对方需要的锁而无法进行其他事务的情况。因为这两个事务都在等待资源变得可用,所以两个都不会释放它持有的锁。

数据库死锁,是最难调试与追踪的。所以本文记录一些死锁调试的思路。

# 死锁例子

以下示例说明了锁定请求将导致死锁时如何发生错误。该示例涉及两个事务A和B。

首先,创建一个包含一行的表,然后开始事务A。在事务中,A事务中对i=1的行加上S锁:

CREATE TABLE t (i INT) ENGINE = InnoDB;
INSERT INTO t (i) VALUES(1);
#A事务
START TRANSACTION;
SELECT * FROM t WHERE i = 1 FOR SHARE;
1
2
3
4
5

B事务删除 i=1 的行,删除操作需要一个X锁。无法授予该行的S锁,因为它与事务A持有的锁不兼容 ,因此事务B阻塞

#B事务
DELETE FROM t WHERE i = 1;
1
2

最后,事务A还尝试从表中删除该行:

#A事务
 DELETE FROM t WHERE i = 1;
1
2

此处发生死锁,因为事务A需要 X锁才能删除该行。但是事务B已经有一个X锁定请求,并且正在等待客户端A释放其S锁定。所以进入了互相等待的死锁结果, InnoDB为其中一个客户端生成错误并释放其锁。客户端返回此错误:

ERROR 1213 (40001): Deadlock found when trying to get lock;
try restarting transaction
1
2

因为MySQL的死锁检查机制,自动回滚影响最小的事务(事务中插入、更新或删除的行数确定),解除死锁。

# 死锁检测机制

InnoDB自动检测事务的死锁和回退事务解决死锁问题。 InnoDB尝试选择要回滚的小事务,其中事务的大小由插入,更新或删除的行数确定。

#查看事务阻塞时间
show VARIABLES like 'innodb_lock_wait_timeout'
#设置等待锁时间
SET innodb_lock_wait_timeout= some_number
#查看死锁是否自动回滚
show VARIABLES like 'innodb_deadlock_detect'
# 启动关闭死锁检测
SET innodb_deadlock_detect=0/1
1
2
3
4
5
6
7
8

# 处理死锁

# 查找死锁

  1. 最近一次死锁 在任何时候,发出以下命令以确定最近死锁的原因。然后调整代码以避免死锁。
SHOW ENGINE INNODB STATUS
1
  1. 所有死锁 通过启用innodb_print_all_deadlocks 配置选项来收集更广泛的调试信息 。有关每个死锁的信息,而不仅仅是最新的死锁,都记录在MySQL 错误日志中。完成调试后,请应该禁用此选项。
#查询是否启用所有死锁信息保存到日志
show variables like 'innodb_print_all_deadlocks';
set innodb_print_all_deadlocks=0/1;
1
2
3

# 定位死锁

比如上面那个死锁例子,通过SHOW ENGINE INNODB STATUS命令拿到最近的死锁信息得到以下结果。

------------------------
LATEST DETECTED DEADLOCK
------------------------
2020-08-19 18:46:57 0x1ee0
*** (1) TRANSACTION:
TRANSACTION 87305, ACTIVE 3 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 1136, 1 row lock(s)
MySQL thread id 9, OS thread handle 15096, query id 154 localhost ::1 root updating
DELETE FROM t WHERE i = 1

*** (1) HOLDS THE LOCK(S):
RECORD LOCKS space id 163 page no 4 n bits 72 index GEN_CLUST_INDEX of table `area_data`.`t` trx id 87305 lock_mode X waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
 0: len 6; hex 000000000200; asc       ;;
 1: len 6; hex 000000015348; asc     SH;;
 2: len 7; hex 820000008b0110; asc        ;;
 3: len 4; hex 80000001; asc     ;;


*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 163 page no 4 n bits 72 index GEN_CLUST_INDEX of table `area_data`.`t` trx id 87305 lock_mode X waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
 0: len 6; hex 000000000200; asc       ;;
 1: len 6; hex 000000015348; asc     SH;;
 2: len 7; hex 820000008b0110; asc        ;;
 3: len 4; hex 80000001; asc     ;;


*** (2) TRANSACTION:
TRANSACTION 87306, ACTIVE 6 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 4 lock struct(s), heap size 1136, 3 row lock(s)
MySQL thread id 8, OS thread handle 6104, query id 158 localhost ::1 root updating
DELETE FROM t WHERE i = 1

*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 163 page no 4 n bits 72 index GEN_CLUST_INDEX of table `area_data`.`t` trx id 87306 lock mode S
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
 0: len 8; hex 73757072656d756d; asc supremum;;

Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
 0: len 6; hex 000000000200; asc       ;;
 1: len 6; hex 000000015348; asc     SH;;
 2: len 7; hex 820000008b0110; asc        ;;
 3: len 4; hex 80000001; asc     ;;


*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 163 page no 4 n bits 72 index GEN_CLUST_INDEX of table `area_data`.`t` trx id 87306 lock_mode X waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
 0: len 6; hex 000000000200; asc       ;;
 1: len 6; hex 000000015348; asc     SH;;
 2: len 7; hex 820000008b0110; asc        ;;
 3: len 4; hex 80000001; asc     ;;

*** WE ROLL BACK TRANSACTION (1)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

主题流程可以看到,事务2持有S锁,然后事务1请求X锁,然后事务2也去请求X锁,结果失败了执行回滚了

# 参考

官方文档-Deadlocks in InnoDB (opens new window)

在 GitHub 编辑此页 (opens new window)
上次更新: 2024/02/25, 12:11:11
MySQL调优利器Explain
MySQL之Gap-Locks与Next-key-Locks

← MySQL调优利器Explain MySQL之Gap-Locks与Next-key-Locks→

Theme by Vdoing | Copyright © 2018-2024 unclezs
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式