mysql死锁(dead lock)与锁等待(lock wait)

news/2024/11/28 17:40:25/

很多人都分不清死锁和锁等待的区别,也有不同IT口的人叫法的差异。在运维侧:

死锁最明显的特征是会自动解开,是需要我们去事后解决逻辑缺陷。

锁等待则是业务卡住了(一般是某个大事务还在执行,或有事务没提交),需要杀掉持有锁的进城让业务正常进行

做几个实验详细演示一下。

表结构及数据情况

mysql> desc ttt;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| x     | int(11)     | NO   | PRI | NULL    |       |
| y     | datetime    | YES  |     | NULL    |       |
| z     | varchar(10) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.00 sec)mysql> select * from ttt;
+---+---------------------+------+
| x | y                   | z    |
+---+---------------------+------+
| 1 | 2023-05-30 23:50:13 | 123  |
| 2 | 2023-04-26 17:58:18 | av3  |
| 3 | 2023-05-30 22:52:35 | at   |
| 4 | 2023-04-26 17:58:29 | attt |
| 5 | 2023-05-30 22:52:55 | zxz  |
+---+---------------------+------+
5 rows in set (0.00 sec)

死锁(dead lock)

上文说了,死锁会自动解除,这里主要展示一下怎么追查。这里就不演示具体执行顺序了

前台报错

session1,这个先持有

mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> update ttt set y=now() where x=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0mysql>  update ttt set y=now() where x=3;
Query OK, 1 row affected (7.04 sec)
Rows matched: 1  Changed: 1  Warnings: 0mysql> 

session2,这个来跳出错误

mysql> begin;
Query OK, 0 rows affected (0.00 sec)mysql> update ttt set y=now() where x=3;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0mysql>  update ttt set y=now() where x=1;
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
mysql> 

事后追查

innodb status的last dead lock只会记录上一次,建议是使用innodb_print_all_deadlocks参数,将记录打印到error.log中,该参数默认为off,可以动态修改

mysql> show variables like '%innodb_print_all_deadlocks%';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| innodb_print_all_deadlocks | OFF   |
+----------------------------+-------+
1 row in set (0.00 sec)mysql> set global innodb_print_all_deadlocks=on;
Query OK, 0 rows affected (0.00 sec)mysql> show variables like '%innodb_print_all_deadlocks%';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| innodb_print_all_deadlocks | ON    |
+----------------------------+-------+
1 row in set (0.00 sec)

innodb status

show engine innodb status;*********------------------------
LATEST DETECTED DEADLOCK
------------------------
2023-05-30 22:42:09 0x7f9fd41ba700
*** (1) TRANSACTION:
TRANSACTION 5454, ACTIVE 26 sec starting index read
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 18, OS thread handle 140324434298624, query id 440 localhost root updating
update ttt set y=now() where x=3
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 23 page no 3 n bits 80 index PRIMARY of table `ddd`.`ttt` trx id 5454 lock_mode X locks rec but not gap waiting
Record lock, heap no 10 PHYSICAL RECORD: n_fields 5; compact format; info bits 00: len 4; hex 80000003; asc     ;;1: len 6; hex 00000000154f; asc      O;;2: len 7; hex 390000014e0110; asc 9   N  ;;3: len 5; hex 99b03d6a76; asc   =jv;;4: len 2; hex 6174; asc at;;*** (2) TRANSACTION:
TRANSACTION 5455, ACTIVE 15 sec starting index read
mysql tables in use 1, locked 1
3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
MySQL thread id 20, OS thread handle 140324435109632, query id 441 localhost root updating
update ttt set y=now() where x=1
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 23 page no 3 n bits 80 index PRIMARY of table `ddd`.`ttt` trx id 5455 lock_mode X locks rec but not gap
Record lock, heap no 10 PHYSICAL RECORD: n_fields 5; compact format; info bits 00: len 4; hex 80000003; asc     ;;1: len 6; hex 00000000154f; asc      O;;2: len 7; hex 390000014e0110; asc 9   N  ;;3: len 5; hex 99b03d6a76; asc   =jv;;4: len 2; hex 6174; asc at;;*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 23 page no 3 n bits 80 index PRIMARY of table `ddd`.`ttt` trx id 5455 lock_mode X locks rec but not gap waiting
Record lock, heap no 7 PHYSICAL RECORD: n_fields 5; compact format; info bits 00: len 4; hex 80000001; asc     ;;1: len 6; hex 00000000154e; asc      N;;2: len 7; hex 380000014d0110; asc 8   M  ;;3: len 5; hex 99b03d6a6b; asc   =jk;;4: len 3; hex 313233; asc 123;;*** WE ROLL BACK TRANSACTION (2)********

error.log

[root@mysql57-1 data]# tail -100f mysql57-1.err 
2023-05-25T07:42:37.677851Z 14 [Note] Access denied for user 'root'@'localhost' (using password: YES)
2023-05-25T07:44:15.360390Z 15 [Note] Access denied for user 'roo'@'localhost' (using password: YES)
2023-05-25T07:44:28.477560Z 16 [Note] Access denied for user 'roo'@'localhost' (using password: YES)
2023-05-30T14:53:00.101403Z 22 [Note] InnoDB: Transactions deadlock detected, dumping detailed information.
2023-05-30T14:53:00.101475Z 22 [Note] InnoDB: 
*** (1) TRANSACTION:TRANSACTION 5458, ACTIVE 25 sec starting index read
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 21, OS thread handle 140324434298624, query id 473 localhost root updating
update ttt set y=now() where x=5
2023-05-30T14:53:00.101516Z 22 [Note] InnoDB: *** (1) WAITING FOR THIS LOCK TO BE GRANTED:RECORD LOCKS space id 23 page no 3 n bits 80 index PRIMARY of table `ddd`.`ttt` trx id 5458 lock_mode X locks rec but not gap waiting
Record lock, heap no 6 PHYSICAL RECORD: n_fields 5; compact format; info bits 00: len 4; hex 80000005; asc     ;;1: len 6; hex 000000001553; asc      S;;2: len 7; hex 3b00000130036d; asc ;   0 m;;3: len 5; hex 99b03d6d32; asc   =m2;;4: len 3; hex 7a787a; asc zxz;;2023-05-30T14:53:00.101718Z 22 [Note] InnoDB: *** (2) TRANSACTION:TRANSACTION 5459, ACTIVE 10 sec starting index read
mysql tables in use 1, locked 1
3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
MySQL thread id 22, OS thread handle 140324435109632, query id 474 localhost root updating
update ttt set y=now() where x=3
2023-05-30T14:53:00.101748Z 22 [Note] InnoDB: *** (2) HOLDS THE LOCK(S):RECORD LOCKS space id 23 page no 3 n bits 80 index PRIMARY of table `ddd`.`ttt` trx id 5459 lock_mode X locks rec but not gap
Record lock, heap no 6 PHYSICAL RECORD: n_fields 5; compact format; info bits 00: len 4; hex 80000005; asc     ;;1: len 6; hex 000000001553; asc      S;;2: len 7; hex 3b00000130036d; asc ;   0 m;;3: len 5; hex 99b03d6d32; asc   =m2;;4: len 3; hex 7a787a; asc zxz;;2023-05-30T14:53:00.101912Z 22 [Note] InnoDB: *** (2) WAITING FOR THIS LOCK TO BE GRANTED:RECORD LOCKS space id 23 page no 3 n bits 80 index PRIMARY of table `ddd`.`ttt` trx id 5459 lock_mode X locks rec but not gap waiting
Record lock, heap no 10 PHYSICAL RECORD: n_fields 5; compact format; info bits 00: len 4; hex 80000003; asc     ;;1: len 6; hex 000000001552; asc      R;;2: len 7; hex 3a0000012e03d1; asc :   .  ;;3: len 5; hex 99b03d6d23; asc   =m#;;4: len 2; hex 6174; asc at;;2023-05-30T14:53:00.102084Z 22 [Note] InnoDB: *** WE ROLL BACK TRANSACTION (2)

锁等待(lock wait)

1个参数

innodb_lock_wait_timeout

行锁等待的时间,如果超过这个时间,session2(后发起那个)会自动跳出

session1

mysql> begin;
Query OK, 0 rows affected (0.00 sec)mysql> update ttt set y=now() where x=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

session2

mysql> update ttt set y=now() where x=1;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

怎么处理

省略构造锁

通过information_schema.innodb_lock_waits视图获得锁等待的关系

mysql> select * from information_schema.innodb_lock_waits;
+-------------------+-------------------+-----------------+------------------+
| requesting_trx_id | requested_lock_id | blocking_trx_id | blocking_lock_id |
+-------------------+-------------------+-----------------+------------------+
| 5467              | 5467:23:3:7       | 5466            | 5466:23:3:7      |
+-------------------+-------------------+-----------------+------------------+
1 row in set, 1 warning (0.00 sec)

再结合information_schema.innodb_trx视图得到语句和线程ID

这里提供一个sql

SELECT r.trx_id waiting_trx_id,  r.trx_mysql_thread_id waiting_thread,r.trx_query waiting_query,b.trx_id blocking_trx_id, b.trx_mysql_thread_id blocking_thread,b.trx_query blocking_query,b.trx_autocommit_non_lockingFROM       information_schema.innodb_lock_waits wINNER JOIN information_schema.innodb_trx b  ON  b.trx_id = w.blocking_trx_id
INNER JOIN information_schema.innodb_trx r  ON  r.trx_id = w.requesting_trx_id;mysql> SELECT r.trx_id waiting_trx_id,  ->      r.trx_mysql_thread_id waiting_thread,->      r.trx_query waiting_query,->      b.trx_id blocking_trx_id, ->      b.trx_mysql_thread_id blocking_thread,->      b.trx_query blocking_query,->  b.trx_autocommit_non_locking->  FROM       information_schema.innodb_lock_waits w->  INNER JOIN information_schema.innodb_trx b  ON  ->   b.trx_id = w.blocking_trx_id-> INNER JOIN information_schema.innodb_trx r  ON  ->   r.trx_id = w.requesting_trx_id;
+----------------+----------------+----------------------------------+-----------------+-----------------+----------------+----------------------------+
| waiting_trx_id | waiting_thread | waiting_query                    | blocking_trx_id | blocking_thread | blocking_query | trx_autocommit_non_locking |
+----------------+----------------+----------------------------------+-----------------+-----------------+----------------+----------------------------+
| 5470           |             22 | update ttt set y=now() where x=1 | 5466            |              26 | NULL           |                          0 |
+----------------+----------------+----------------------------------+-----------------+-----------------+----------------+----------------------------+
1 row in set, 1 warning (0.00 sec)

再对blocking thread的状态进行确认,然后kill

  mysql> select * from information_schema.PROCESSLIST where id=26;
+----+------+-----------+------+---------+------+-------+------+
| ID | USER | HOST      | DB   | COMMAND | TIME | STATE | INFO |
+----+------+-----------+------+---------+------+-------+------+
| 26 | root | localhost | ddd  | Sleep   | 1221 |       | NULL |
+----+------+-----------+------+---------+------+-------+------+
1 row in set (0.00 sec)

杀线程

mysql> kill 26;
Query OK, 0 rows affected (0.00 sec)

级联锁或大量锁

这里构造一个多个争用的情况。

session1,线程id为27,这个先发起

mysql> begin;
Query OK, 0 rows affected (0.00 sec)mysql> update ttt set y=now() where x=1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

session,线程id为22,第二个发起

mysql> update ttt set y=now() where x=1;

session3,线程id为28,最后一个发起

mysql> update ttt set y=now();

锁关系情况

mysql> select * from information_schema.innodb_lock_waits;
+-------------------+-------------------+-----------------+------------------+
| requesting_trx_id | requested_lock_id | blocking_trx_id | blocking_lock_id |
+-------------------+-------------------+-----------------+------------------+
| 5479              | 5479:23:3:7       | 5478            | 5478:23:3:7      |
| 5479              | 5479:23:3:7       | 5473            | 5473:23:3:7      |
| 5478              | 5478:23:3:7       | 5473            | 5473:23:3:7      |
+-------------------+-------------------+-----------------+------------------+
3 rows in set, 1 warning (0.01 sec)

查询sql的展示情况

mysql> SELECT r.trx_id waiting_trx_id,        r.trx_mysql_thread_id waiting_thread,      r.trx_query waiting_query,      b.trx_id blocking_trx_id,       b.trx_mysql_thread_id blocking_thread,      b.trx_query blocking_query,  b.trx_autocommit_non_locking  FROM       information_schema.innodb_lock_waits w  INNER JOIN information_schema.innodb_trx b  ON     b.trx_id = w.blocking_trx_id INNER JOIN information_schema.innodb_trx r  ON     r.trx_id = w.requesting_trx_id;
+----------------+----------------+----------------------------------+-----------------+-----------------+----------------------------------+----------------------------+
| waiting_trx_id | waiting_thread | waiting_query                    | blocking_trx_id | blocking_thread | blocking_query                   | trx_autocommit_non_locking |
+----------------+----------------+----------------------------------+-----------------+-----------------+----------------------------------+----------------------------+
| 5479           |             28 | update ttt set y=now()           | 5478            |              22 | update ttt set y=now() where x=1 |                          0 |
| 5479           |             28 | update ttt set y=now()           | 5473            |              27 | NULL                             |                          0 |
| 5478           |             22 | update ttt set y=now() where x=1 | 5473            |              27 | NULL                             |                          0 |
+----------------+----------------+----------------------------------+-----------------+-----------------+----------------------------------+----------------------------+

这个时候一般的做法是先找到最多的那个blocking_thread

确认他的进程状态后来考虑是否杀

如果他是活动的thread,在干活,就可以删掉释放资源。

如果他是非活动,就要看他这个thread的blocking_thread,找到活动持有资源的,来杀掉。

当然也有执行了完了不提交的情况,innodb_trx的trx_autocommit_non_locking列的值就是为了标记是否是提交了。0表示没有提交。

学习原理,孵化思路。积累工具,下笔有道。


http://www.ppmy.cn/news/109748.html

相关文章

违章停车车牌识别:使用YOLOv5进行车牌检测与识别

文末含有完整代码 目录 介绍准备工作数据集准备训练YOLOv5模型车牌识别违章停车检测总结与展望 1. 介绍 违章停车问题在城市中是一个很常见的交通问题。为了有效地管理违章停车问题,我们需要对违停车辆进行识别。本篇博客将向您展示如何使用YOLOv5进行车牌检测与…

C#初步了解复杂数据类型,函数方法和排序

文章目录 1.复杂数据类型(1)枚举(2)数组(3)结构体 2.数值型和引用类型3.函数4. 初级排序 1.复杂数据类型 (1)枚举 枚举是一组命名整型常量。枚举类型是使用 enum 关键字声明的。 …

Scala基本语法

1.注释 Scala注释使用和Java完全一样。 注释是一个程序员必须要具有的良好编程习惯。 将自己的思想通过注释先整理出来,再用代码去体现。 基本语法 单行注释:// 多行注释:/* */ 文档注释: /** * */ 2.变量和常量 基本语法 va…

EclipseCDT远程交叉编译远程单步调试基于makefile例程(实测有效)

文章目录 前言:1. 新建工程2. 远程编译环境配置2.1 下载sshfs并挂载目录2.2 Debug配置2.3安装EclipseCDT的远程插件2.4 拷贝gdbserver 3. 调试总结: 前言: 之前写过一篇VSCode远程调试linux,当时是把程序以及代码通过远程的方式,…

有奖励!2023陕西省首台(套)重大技术装备产品项目申报条件、认定材料

本文整理了2023陕西省首台(套)重大技术装备产品项目申报条件,认定材料等相关内容,感兴趣的朋友快跟小编一起来看看吧! 一、重点支持方向及领域 重点支持方向及领域:高档工业母机、电力装备、大型矿山和冶金…

Transformer 估算 101

本文主要介绍用于估算 transformer 类模型计算量需求和内存需求的相关数学方法。 引言 其实,很多有关 transformer 语言模型的一些基本且重要的信息都可以用很简单的方法估算出来。不幸的是,这些公式在 NLP 社区中鲜为人知。本文的目的是总结这些公式&…

pyest+appium实现APP自动化测试

目录 01、appium环境搭建 2、搭建pythonpytestappium环境 3、安装pycharm搭建项目编写脚本 4、执行测试 绵薄之力 01、appium环境搭建 安装nodejs http://nodejs.cn/ 为什么要安装nodejs? 因为appium这个工具的服务端是由nodejs语言开发的 安装jdk&#x…

python笔记16_实例练习_二手车折旧分析p1

python数据分析练习,具体数据不放出。 分析实践很简单。目的不是做完,而是讲清楚每一步的目的和连带的知识点(所以才叫学习笔记) 0.数据准备 原始数据格式:csv文件 原始数据结构: 数据格式 字段名 int…