Mysql - InnoDB 锁等待,死锁的排查语句

本文介绍了如何排查MySQL InnoDB存储引擎的锁等待和死锁问题,包括使用SHOW OPEN TABLES、SHOW FULL PROCESSLIST、SELECT FROM INFORMATION_SCHEMA.INNODB_TRX等命令,以及解析INNODB_LOCK_WAITS和INNODB_STATUS的日志信息,帮助数据库管理员有效诊断和解决并发事务中的锁冲突。

导航


1. SHOW OPEN TABLES where In_use > 0

这条语句主要用于查看表的锁竞争情况,where 条件限制了只有存在锁竞争才会显示数据。
显示字段如下:

  • Database
    数据库名称

  • Table
    表名

  • In_use
    表锁会使这个值+1,每个请求行锁而阻塞的线程也会使这个值+1

  • Name_locked
    表名是否被锁定。名称锁定用于诸如删除或重命名表的操作

2. SHOW FULL PROCESSLIST

这条语句显示当前正在运行的线程连接,如果你的权限足够,那么你可以看到全部的用户的线程,否则只能看到你当前用户的线程。
显示字段如下:

  • Id
    线程id,可以使用 kill id 来杀死这条线程。

  • Host
    创建连接的主机地址

  • db
    使用的数据库

  • Command
    线程正在执行的命令的类型。
    具体信息查看 Mysql官网Commom描述

  • Time
    线程处于当前状态的时间(以秒未单位)

  • State
    线程正在执行的操作,事件或者状态
    大多数状态对应于非常快速的操作。如果线程在给定状态下停留许多秒钟,则可能存在需要调查的问题。
    具体信息查看Mysql官网State描述

  • Info
    线程当前正在执行的语句

3.SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX

这条语句显示InnoDb中正在开启的非只读事务的相关信息。
这条语句我们重点关注它是否正在等待锁,以及事务的开始时间。
显示字段如下:

  • TRX_ID
    事务Id

  • TRX_WEIGHT
    事务的权重,反映(未必是准确的)已更改的行和该事务锁定的行数。出现死锁时,InnoDb通常会回滚权重较小的事务。

  • TRX_STATE
    事务执行状态。允许值是 RUNNING,LOCK WAIT, ROLLING BACK,和 COMMITTING。

  • TRX_STARTED
    事务的开始时间

  • TRX_REQUESTED_LOCK_ID
    事务当前正在等待的锁的ID

  • TRX_WAIT_STARTED
    事务等待锁的时间

  • TRX_MYSQL_THREAD_ID
    Mysql的线程id

  • TRX_QUERY
    事务正在执行的SQL语句

  • TRX_OPERATION_STATE
    事务当前的操作状态

  • TRX_TABLES_IN_USE
    事务使用到的表的数量

  • TRX_TABLES_LOCKED
    事务从多少个表中获取了锁

  • TRX_LOCK_STRUCTS
    事务保留的锁数。

  • TRX_LOCK_MEMORY_BYTES
    内存中此事务的锁结构占用的总大小。

  • TRX_ROWS_LOCKED
    此事务的锁定行数

  • TRX_ROWS_MODIFIED
    此事务中已修改和已插入的行数。

  • TRX_CONCURRENCY_TICKETS
    由innodb_concurrency_tickets 系统变量指定的值,该值指示当前事务在被换出之前可以完成多少工作

  • TRX_ISOLATION_LEVEL
    当前事务的隔离级别。

  • TRX_UNIQUE_CHECKS
    当前事务是打开还是关闭唯一检查。例如,它们可能在批量数据加载期间关闭。

  • TRX_FOREIGN_KEY_CHECKS
    当前事务是打开还是关闭唯一检查。例如,它们可能在批量数据加载期间关闭。

  • TRX_LAST_FOREIGN_KEY_ERROR
    最后一个外键错误的详细错误消息(如果有);否则NULL。

  • TRX_ADAPTIVE_HASH_LATCHED
    自适应哈希索引是否被当前事务锁定。(一次仅一个事务可以修改自适应哈希索引。)

  • TRX_ADAPTIVE_HASH_TIMEOUT
    是立即放弃搜索锁存器以获取自适应哈希索引,还是在MySQL的调用之间保留它。当没有自适应哈希索引争用时,此值保持为零,并且语句保留闩锁,直到它们完成为止。在争用期间,它递减计数为零,并且语句在每次查询行后立即释放锁存器。

  • TRX_IS_READ_ONLY
    值为1表示事务是只读的。

  • TRX_AUTOCOMMIT_NON_LOCKING
    值为1表示事务是 SELECT不使用 FOR UPDATE 或者LOCK IN SHARED MODE子句的语句,并且正在autocommit启用状态下执行, 因此事务将仅包含此一条语句。当此列和TRX_IS_READ_ONLY均为1时,InnoDB优化事务以减少与更改表数据的事务相关的开销。

4. SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS

这条语句显示 InnoDB 中产生锁等待的事务信息。
一个锁等待至少会产生两行的数据,分别是等待锁的事务,以及持有锁的事务。
显示字段如下:

  • LOCK_ID
    内部唯一的锁ID号

  • LOCK_TRX_ID
    请求或者持有锁的事务的ID

  • LOCK_MODE
    请求或者持有的锁。允许值S,X, IS,IX, GAP,AUTO_INC,和 UNKNOWN

  • LOCK_TYPE
    锁的类型。允许的值 RECORD用于行级锁定, TABLE表级锁定

  • LOCK_TABLE
    已锁定或包含锁定记录的表的名称

  • LOCK_INDEX
    索引的名称,如果LOCK_TYPE 为 RECORD 则显示;否则NULL

  • LOCK_SPACE
    锁定记录的表空间ID,如果LOCK_TYPE 为 RECORD 则显示;否则NULL

  • LOCK_PAGE
    锁定记录的页码,如果LOCK_TYPE 为 RECORD 则显示;否则NULL

  • LOCK_REC
    页面内锁定记录的堆号,如果LOCK_TYPE 为 RECORD 则显示;否则NULL

  • LOCK_DATA
    与锁关联的数据(如果有)。如果LOCK_TYPE为RECORD,则显示一个值,否则为NULL。
    如果锁定的是唯一索引,则显示的是二级索引的值。
    如果显示的是二级索引,则显示二级索引值并附加主键值。

5.SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS

这条语句显示锁等待的事务的对应信息。
显示字段如下:

  • REQUESTING_TRX_ID
    请求锁的事务id

  • REQUESTED_LOCK_ID
    请求的锁id

  • BLOCKING_TRX_ID
    持有锁的事务id

  • BLOCKING_LOCK_ID
    持有的锁id

6.SHOW ENGINE INNODB STATUS

这条语句显示的是Innodb过去一段时间的运行日志(这里是每一段时间刷新一次,因此未必是最新的)。
排除死锁的时候,我们重点关注 LATEST DETECTED DEADLOCK 这部分内容就好,这部分内容记录的是最近一次死锁的信息。

这部分的内容解析如下,如果需要更详细的 innodb status 内容的解析,可以查看这篇博客

------------------------
LATEST DETECTED DEADLOCK
------------------------
160128  1:51:53  #这里显示了最近一次发生死锁的日期和时间
*** (1) TRANSACTION:
TRANSACTION D20847, ACTIVE 141 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 376, 2 row lock(s)
MySQL thread id 20027, OS thread handle 0x7f0a4c0f8700, query id 1818124 localhost root statistics
select * from test_deadlock where id=2 for update
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 441 page no 3 n bits 72 index `PRIMARY` of table `xiaoboluo`.`test_deadlock` trx id D20847 lock_mode X locks rec but not gap waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
 0: len 4; hex 00000002; asc     ;;
 1: len 6; hex 000000d20808; asc       ;;
 2: len 7; hex ad000001ab011d; asc        ;;
 3: len 4; hex 00000002; asc     ;;
 
*** (2) TRANSACTION:
TRANSACTION D20853, ACTIVE 119 sec starting index read
mysql tables in use 1, locked 1
3 lock struct(s), heap size 1248, 2 row lock(s)
MySQL thread id 20081, OS thread handle 0x7f0a0f020700, query id 1818204 localhost root statistics
select * from test_deadlock where id=1 for update
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 441 page no 3 n bits 72 index `PRIMARY` of table `xiaoboluo`.`test_deadlock` trx id D20853 lock_mode X locks rec but not gap
Record lock, heap no 3 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
 0: len 4; hex 00000002; asc     ;;
 1: len 6; hex 000000d20808; asc       ;;
 2: len 7; hex ad000001ab011d; asc        ;;
 3: len 4; hex 00000002; asc     ;;
 
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 441 page no 3 n bits 72 index `PRIMARY` of table `xiaoboluo`.`test_deadlock` trx id D20853 lock_mode X locks rec but not gap waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
 0: len 4; hex 00000001; asc     ;;
 1: len 6; hex 000000d20808; asc       ;;
 2: len 7; hex ad000001ab0110; asc        ;;
 3: len 4; hex 00000001; asc     ;;
 
*** WE ROLL BACK TRANSACTION (2)
 
这部分内容比较多,下面分段逐一进行解释:
5.2.1 下面这部分显示的是死锁的第一个事务的信息:
*** (1) TRANSACTION:
TRANSACTION D20847, ACTIVE 141 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 376, 2 row lock(s)
MySQL thread id 20027, OS thread handle 0x7f0a4c0f8700, query id 1818124 localhost root statistics
select * from test_deadlock where id=2 for update
TRANSACTION D20847, ACTIVE 141 sec starting index read:这行表示事务D20847ACTIVE 141 sec表示事务处于活跃状态141s,starting index read表示正在使用索引读取数据行
mysql tables in use 1, locked 1#这行表示事务D20847正在使用1个表,且涉及锁的表有1个
LOCK WAIT 3 lock struct(s), heap size 376, 2 row lock(s) #这行表示在等待3把锁,占用内存376字节,涉及2行记录,如果事务已经锁定了几行数据,这里将会有一行信息显示出锁定结构的数目(注意,这跟行锁是两回事)和堆大小,堆的大小指的是为了持有这些行锁而占用的内存大小,Innodb是用一种特殊的位图表来实现行锁的,从理论上讲,它可将每一个锁定的行表示为一个比特,经测试显示,每个锁通常不超过4比特
MySQL thread id 20027, OS thread handle 0x7f0a4c0f8700, query id 1818124 localhost root statistics #这行表示该事务的线程ID信息,操作系统句柄信息,连接来源、用户
select * from test_deadlock where id=2 for update #这行表示事务涉及的SQL
 
5.2.2 下面这一部分显示的是当死锁发生时,第一个事务正在等待的锁等信息:
*** (1) WAITING FOR THIS LOCK TO BE GRANTED: #这行信息表示第一个事务正在等待锁被授予
RECORD LOCKS space id 441 page no 3 n bits 72 index `PRIMARY` of table `xiaoboluo`.`test_deadlock` trx id D20847 lock_mode X locks rec but not gap waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
 0: len 4; hex 00000002; asc     ;;
 1: len 6; hex 000000d20808; asc       ;;
 2: len 7; hex ad000001ab011d; asc        ;;
 3: len 4; hex 00000002; asc     ;;
RECORD LOCKS space id 441 page no 3 n bits 72 index `PRIMARY` of table `xiaoboluo`.`test_deadlock` trx id D20847 lock_mode X locks rec but not gap waiting#这行信息表示等待的锁是一个record lock,空间id是441,页编号为3,大概位置在页的72位处,锁发生在表xiaoboluo.test_deadlock的主键上,是一个X锁,但是不是gap lock。 waiting表示正在等待锁
Record lock, heap no 3 PHYSICAL RECORD: n_fields 4; compact format; info bits 0 #这行表示record lock的heap no 位置
#这部分剩下的内容只对调试才有用。
 0: len 4; hex 00000002; asc     ;;
 1: len 6; hex 000000d20808; asc       ;;
 2: len 7; hex ad000001ab011d; asc        ;;
 3: len 4; hex 00000002; asc     ;;
 
5.2.3 下面这部分是事务二的状态:
*** (2) TRANSACTION:
TRANSACTION D20853, ACTIVE 119 sec starting index read #事务2处于活跃状态119s
mysql tables in use 1, locked 1 #正在使用1个表,涉及锁的表有1个
3 lock struct(s), heap size 1248, 2 row lock(s) #涉及3把锁,2行记录
MySQL thread id 20081, OS thread handle 0x7f0a0f020700, query id 1818204 localhost root statistics
select * from test_deadlock where id=1 for update #第二个事务的SQL
5.2.4 下面这部分是事务二的持有锁信息:
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 441 page no 3 n bits 72 index `PRIMARY` of table `xiaoboluo`.`test_deadlock` trx id D20853 lock_mode X locks rec but not gap
Record lock, heap no 3 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
 0: len 4; hex 00000002; asc     ;;
 1: len 6; hex 000000d20808; asc       ;;
 2: len 7; hex ad000001ab011d; asc        ;;
 3: len 4; hex 00000002; asc     ;;

RECORD LOCKS space id 441 page no 3 n bits 72 index `PRIMARY` of table `xiaoboluo`.`test_deadlock` trx id D20853 lock_mode X locks rec but not gap
Record lock, heap no 3 PHYSICAL RECORD: n_fields 4; compact format; info bits 0 #从这两行持有锁信息计息后面几行调试信息上看,就是事务1正在等待的锁。
 
5.2.5 下面这部分是事务二正在等待的锁,从下面的信息上看,等待的是同一个表,同一个索引,同一个page上的record lock X锁,但是heap no位置不同,即不同的行上的锁:
*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 441 page no 3 n bits 72 index `PRIMARY` of table `xiaoboluo`.`test_deadlock` trx id D20853 lock_mode X locks rec but not gap waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 0 
 0: len 4; hex 00000001; asc     ;;
 1: len 6; hex 000000d20808; asc       ;;
 2: len 7; hex ad000001ab0110; asc        ;;
 3: len 4; hex 00000001; asc     ;;
*** WE ROLL BACK TRANSACTION (2) #这个表示事务2被回滚,因为两个事务的回滚开销一样,所以选择了后提交的事务进行回滚,如果两个事务回滚的开销不同(undo 数量不同),那么就回滚开销最小的那个事务。

本文参考:
MYSQL官方说明文档
小萝卜博客-mysql之show engine innodb status解读

<think>首先,用户的问题是基于提供的引用材料:"我想查找在MySQL排查死锁语句 请问MySQL排查死锁语句"。用户想要知道在MySQL排查死锁的具体语句。 从系统级指令: - 所有行内数学表达式必须使用 $...$ 格式,但这里涉及的是MySQL语句,不是数学表达式,所以不需要。 - 独立公式使用 $$...$$,但也不适用。 - LaTeX语法正确:确保语法正确,但这里主要是SQL语句- 使用中文回答。 - 生成相关问题:在回答后,需要生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识:比如[^1]、[^2]等。 用户提供了多个引用: - 引用[1]:描述数据准备一个事务ID查询。 - 引用[2]:列出查询是否存在表的语句,包括查看事务、等待等。 - 引用[3]:解释死锁检测机制处理方式。 - 引用[4]:定义死锁重要性。 - 引用[5]:提到获取死锁日志的命令。 用户的核心问题是:"MySQL排查死锁语句"。所以,我需要从引用中提取相关的SQL语句。 关键语句来自引用[2]引用[5]: - 引用[2]: - 查看正在进行中的事务:`SELECT * FROM information_schema.INNODB_TRX` - 查看正在的事务:`SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;`(注意:在MySQL 8.0中,INNODB_LOCKS表已弃用,建议使用其他视图) - 查看等待的事务:`SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;` - 查询是否表:`SHOW OPEN TABLES where In_use > 0;` - 查看最近死锁的日志:`show engine innodb status` - 引用[5]: - 获取死锁日志:`SHOW ENGINE INNODB STATUS` 在引用[1]中,也有一个查询事务ID的语句:`select trx_id from information_schema.innodb_trx order by trx_started desc limit 1;` 用户说"上述引用仅供参考",但我应该尽可能参考用户的引用。用户的上一次问题是关于MySQL死锁排查语句,所以我需要基于这些引用构建回答。 回答结构: - 必须结构清晰,帮助用户逐步解决问题。 - 尽量保证回答真实可靠:基于提供的引用,并结合一般知识。 步骤: 1. **介绍排查死锁的常用语句**:从引用中提取。 2. **解释每个语句的用途**:确保用户理解。 3. **添加引用标识**:在引用的段落末尾添加如[^2]、[^5]。 4. **生成相关问题**:在回答后,添加相关问题部分。 生成的语句- `SHOW ENGINE INNODB STATUS`:用于获取死锁日志,包含死锁详情。 - `SELECT * FROM information_schema.INNODB_TRX`:查看当前事务。 - `SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS`:查看等待- `SHOW OPEN TABLES`:查看定的表。 - 其他相关的:如`KILL`命令来终止事务(从引用[2])。 在MySQL 8.0中,一些视图可能变了,但引用中提到的是标准做法。 完整回答: - 先简要解释死锁排查- 然后列出语句- 在末尾添加引用标识。 相关问题生成: - 基于主题,如如何优化死锁死锁预防策略等。 最终回答大纲: 1. **排查死锁语句**: - 使用 `SHOW ENGINE INNODB STATUS` 获取死锁日志。 - 查询事务:`SELECT * FROM information_schema.INNODB_TRX` - 查看等待:`SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS` - 查看定的表:`SHOW OPEN TABLES WHERE In_use > 0` - 终止事务:`KILL [process_id]` 2. **添加引用**:在每个语句后或描述后自然地标注引用。 3. **相关问题**:生成几个相关问题。 </think>### MySQL死锁排查语句详解 在MySQL排查死锁问题时,主要通过查询系统视图内置命令来获取事务、资源死锁详情。以下是基于权威引用整理的核心排查语句,每个语句都配有解释执行示例。这些步骤能帮助您逐步定位死锁原因(例如事务冲突或资源竞争),确保数据库性能稳定。 #### 1. **查看当前进行中的事务** - **用途**:列出所有活跃事务的详细信息,包括事务ID、状态等待情况,帮助识别可能陷入死锁的事务[^2][^5]。 - **语句**: ```sql SELECT * FROM information_schema.INNODB_TRX; ``` - **示例输出**:事务ID(`trx_id`)、事务状态(`trx_state`)等字段,如事务状态为`LOCK WAIT`表示正在等待。 #### 2. **查看等待情况** - **用途**:显示事务之间的依赖关系,找出哪些事务在互相等待资源,是排查死锁的关键[^2][^5]。 - **语句**: ```sql SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS; ``` - **关键字段**:`requesting_trx_id`(请求的事务)、`blocking_trx_id`(持有的事务),可直接定位死锁链条。 #### 3. **检查表级状态** - **用途**:快速识别哪些表被定及其使用计数,适用于排查因表导致的死锁[^2]。 - **语句**: ```sql SHOW OPEN TABLES WHERE In_use > 0; ``` - **输出说明**:`In_use`列大于0表示表被定,例如`In_use=2`表示两个会话正在竞争该表资源。 #### 4. **获取死锁详细日志** - **用途**:查看最近发生的死锁事件详情,包括冲突的SQL语句、事务回滚记录,是诊断死锁根源的最有效命令[^3][^5]。 - **语句**: ```sql SHOW ENGINE INNODB STATUS; ``` - **日志解析**:在输出中查找`LATEST DETECTED DEADLOCK`部分,包含: - 死锁事务的SQL语句- 资源争夺细节(如行或间隙)。 - 被回滚的事务ID(标记为`WE ROLL BACK TRANSACTION`)。 #### 5. **终止死锁事务(可选)** - **用途**:当死锁导致系统僵死时,强制终止相关事务以解除死锁[^2]。 - **步骤**: 1. 先查询事务进程ID: ```sql SELECT * FROM information_schema.INNODB_TRX; -- 或 SHOW PROCESSLIST; ``` 2. 终止进程: ```sql KILL [process_id]; -- 替换为实际ID,例如 KILL 12345; ``` 3. 验证是否释放: ```sql SHOW OPEN TABLES WHERE In_use > 0; -- 确保In_use=0 ``` ### 排查建议流程 1. **初步检测**:运行`SHOW ENGINE INNODB STATUS`快速获取死锁日志[^5]。 2. **分析事务**:结合`INNODB_TRX``INNODB_LOCK_WAITS`定位冲突事务[^2]。 3. **终止与恢复**:必要时使用`KILL`命令,并重试事务[^3]。 4. **预防优化**:调整事务隔离级别或设置超时参数(如`innodb_lock_wait_timeout`)以减少死锁频率[^3][^4]。 > **注意**:在MySQL 8.0及以上版本,部分视图(如`INNODB_LOCKS`)已弃用,推荐优先使用上述语句。所有命令需在数据库管理员权限下执行,避免影响生产环境[^2][^5]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值