Mysql查看死锁与解除死锁的深入讲解

yizhihongxing

Mysql查看死锁与解除死锁的深入讲解

什么是死锁

在多个并发事务中,每个事务都需要访问其他事务持有的资源时,如果某个事务因为等待资源而被阻塞,同时它又持有其他事务需要的资源,就会发生死锁现象。

查看死锁

可以使用以下命令查看Mysql中的死锁信息:

SHOW ENGINE INNODB STATUS;

该命令会返回一个INNODB STATUS的输出,其中包含有关当前事务和锁定状态的信息,包括死锁信息。

在输出中找到“LATEST DETECTED DEADLOCK”这一行,它将提供有关最新检测到的死锁的信息。例如:

LATEST DETECTED DEADLOCK
------------------------
2020-07-14 12:00:00 0x7f0f4b909700
*** (1) TRANSACTION:
TRANSACTION 21387481, ACTIVE 0 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 10 lock struct(s), heap size 1136, 3 row lock(s)
MySQL thread id 1234567, OS thread handle 47151658949888, 

*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 134463 page no 51 n bits 288 index ux_id of table `db`.`test` trx id 21387481 lock_mode X waiting
Record lock, heap no 8 PHYSICAL RECORD: n_fields 9; compact format; info bits 32

*** (2) TRANSACTION:
TRANSACTION 21387485, ACTIVE 0 sec fetching rows
mysql tables in use 1, locked 1
6 lock struct(s), heap size 1136, 8 row lock(s), undo log entries 6
MySQL thread id 1234568, OS thread handle 47131778237296, 

*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 134463 page no 51 n bits 288 index ux_id of table `db`.`test` trx id 21387485 lock_mode X
Record lock, heap no 8 PHYSICAL REDO n_fields 9; compact format; info bits 32

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 134463 page no 51 n bits 288 index ux_id of table `db`.`test` trx id 21387485 lock_mode X locks rec but not gap waiting
Record lock, heap no 4 PHYSICAL RECORD: n_fields 9; compact format; info bits 32

*** WE ROLL BACK TRANSACTION (2)

解除死锁

当发生死锁时,需要手动解除死锁。可以在Mysql客户端使用以下语句来解除死锁:

KILL <thread_id>;

其中<thread_id>为发生死锁的线程ID。

同时,也可以将innodb_lock_wait_timeout设置为一个较小的值,以尽快检测和解除死锁。例如:

SET innodb_lock_wait_timeout = 120;

当等待锁定时间超过120秒时,将自动解除死锁。

示例说明

下面是两个关于Mysql死锁的示例:

示例一

假设表t1t2中都有数据,执行以下事务:

-- 事务一
START TRANSACTION;
UPDATE t1 SET c1 = c1 + 1 WHERE id = 1;
UPDATE t2 SET c2 = c2 + 1 WHERE id = 1;
COMMIT;

-- 事务二
START TRANSACTION;
UPDATE t2 SET c2 = c2 + 1 WHERE id = 1;
UPDATE t1 SET c1 = c1 + 1 WHERE id = 1;
COMMIT;

如果以上两个事务同时进行,就会陷入死锁现象。可以通过查看死锁信息来找到故障源并解除死锁。假设输出如下:

LATEST DETECTED DEADLOCK
------------------------
2020-07-14 12:00:00 0x7f0f4b909700
*** (1) TRANSACTION:
TRANSACTION 21387481, ACTIVE 0 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 10 lock struct(s), heap size 1136, 3 row lock(s)
MySQL thread id 1234567, OS thread handle 47151658949888, 

*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 134463 page no 51 n bits 288 index ux_id of table `db`.`t1` trx id 21387481 lock_mode X waiting
Record lock, heap no 8 PHYSICAL RECORD: n_fields 9; compact format; info bits 32

*** (2) TRANSACTION:
TRANSACTION 21387485, ACTIVE 0 sec fetching rows
mysql tables in use 1, locked 1
6 lock struct(s), heap size 1136, 8 row lock(s), undo log entries 6
MySQL thread id 1234568, OS thread handle 47131778237296, 

*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 134463 page no 51 n bits 288 index ux_id of table `db`.`t1` trx id 21387485 lock_mode X
Record lock, heap no 8 PHYSICAL REDO n_fields 9; compact format; info bits 32

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 134463 page no 51 n bits 416 index PRIMARY of table `db`.`t2` trx id 21387485 lock_mode X locks rec but not gap waiting
Record lock, heap no 4 PHYSICAL RECORD: n_fields 2; compact format; info bits 0

*** WE ROLL BACK TRANSACTION (2)

第一个事务(线程ID为21387481)正在等待表t1的锁,而第二个事务(线程ID为21387485)则正在持有表t1的锁,并在等待表t2的锁。因此,第二个事务被回滚以解除死锁。

示例二

假设表t中有数据,执行以下单个事务:

START TRANSACTION;
UPDATE t SET c = c + 1 WHERE id = 1;
UPDATE t SET c = c + 1 WHERE id = 2; -- 将where条件改为id = 1
COMMIT;

在第二个UPDATE语句中,将WHERE条件从id = 2更改为id = 1,这会导致在更新表之前发生死锁。

当执行该事务时,Mysql可能会输出以下消息:

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

此时可以使用SHOW ENGINE INNODB STATUS来查看死锁信息,然后手动解除死锁。需要注意的是,Mysql在发生死锁时会自动回滚修改,因此不需要手动恢复数据。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Mysql查看死锁与解除死锁的深入讲解 - Python技术站

(0)
上一篇 2023年5月21日
下一篇 2023年5月21日

相关文章

  • 在Mariadb中创建数据库-九五小庞

    MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可 MariaDB的目的是完全兼容MySQL,包括API和命令行,使之能轻松成为MySQL的代替品。在存储引擎方面,使用XtraDB来代替MySQL的InnoDB。  MariaDB基于事务的Maria存储引擎,替换了MySQL的MyISAM存储引擎,它使用了Perco…

    MySQL 2023年4月12日
    00
  • mybatis中foreach报错:_frch_item_0 not found的解决方法

    针对mybatis中foreach报错:“_frch_item_0 not found”的解决方法,我将提供以下完整攻略。 问题分析 通过对mybatis中foreach的使用进行分析,可以得出使用foreach时,需要保证以下几点: collection属性必须设置为可遍历的集合类型(比如List、Set等)。 item属性必须设置,不然会报错。 当col…

    database 2023年5月21日
    00
  • SQL语句练习实例之三——平均销售等待时间

    这里是SQL语句练习实例之三——平均销售等待时间的完整攻略。 问题描述 假设我们有一个销售系统,里面有两张表: sales 表,包含销售的信息,包括销售的时间、销售员和销售的数量等; salesman 表,包含销售员的信息,包括销售员的编号和姓名等。 现在需要我们统计每个销售员的平均销售等待时间,即从销售员服务的第一个客户进入销售系统开始计算,到最后一个客户…

    database 2023年5月21日
    00
  • SQL中代替Like语句的另一种写法

    SQL中代替Like语句的另一种写法是使用正则表达式。正则表达式是一种描述文本模式的方法,我们可以用它来匹配、查找和替换文本中的字符。 在SQL中,可以使用RLIKE或REGEXP操作符实现正则表达式匹配,代替Like语句。 下面是使用RLIKE操作符实现正则表达式匹配的语法: SELECT * FROM table_name WHERE column_na…

    database 2023年5月19日
    00
  • 清除minerd进程的简单方法

    清除 minerd 进程的简单方法主要涉及到查找 minerd 进程及其相关信息,然后使用一些系统和命令行操作来停止和删除该进程。具体步骤如下: 步骤一:查找 minerd 进程及其相关信息 打开终端程序,输入以下命令: ps aux | grep minerd 该命令会列出所有与 minerd 进程相关的信息,包括进程ID、CPU占用率等。 查找进程ID号…

    database 2023年5月22日
    00
  • 详解PHP中的PDO类

    详解PHP中的PDO类 简介 PDO(PHP Data Object)是PHP中的一个数据库抽象层,提供了面向对象的操作数据库的方式,可以支持多种数据库。PDO类是PHP对数据库进行操作的一个核心类。 PDO类的初始化 使用PDO时需要先初始化,初始化后可以操作数据库。PDO的初始化需要指定数据库类型、主机(或IP地址)、数据库名、用户名、密码。下面是一个示…

    database 2023年5月21日
    00
  • 在linux命令下导出导入.sql文件的方法

    当需要备份或恢复MySQL数据库时,我们可以使用导出和导入SQL文件的方法来完成。在Linux命令行下,我们可以通过以下步骤来导出或导入SQL文件。 导出SQL文件 首先登录到MySQL服务器 bash mysql -u username -p 在提示符下输入密码。 选择需要导出的数据库 bash use database_name; 将 database_…

    database 2023年5月22日
    00
  • .Net平台开发实践的一些点滴总结(技术规范与实践精华)

    .Net平台开发实践的一些点滴总结(技术规范与实践精华)攻略 简介 本篇文章主要介绍在.Net平台上的开发实践,包括技术规范和实践精华。 技术规范 1. 代码规范 在开发中,我们需要遵循一些代码规范,以保证代码的一致性和可维护性。以下是.Net平台开发中一些代码规范: 命名规范:命名应该具有意义并且易于阅读,例如类名应该使用名词单数形式,方法名应该使用动词开…

    database 2023年5月21日
    00
合作推广
合作推广
分享本页
返回顶部