为什么MySQL升级后死锁检测机制变得更加频繁以及如何调整?

梦涛姑娘_1073

梦涛姑娘_1073

2026-08-01

487人浏览

原创

mysql 8.0死锁报错激增并非死锁变多,而是默认开启且更激进的innodb_deadlock_detect将原被静默忽略的环形等待全部检测并中止;5.7中该参数常被手动关闭,而8.0默认on,通过死锁图遍历主动回滚,与innodb_lock_wait_timeout超时机制无关。

为什么mysql升级后死锁检测机制变得更加频繁以及如何调整?

MySQL 8.0 默认开启 innodb_deadlock_detect,不是“变多”而是“全报了”

你看到的 Deadlock found when trying to get lock 错误激增,大概率不是死锁真的变多了,而是 MySQL 8.0 把原来被静默忽略的环形等待全检测并中止了。5.7 中这个参数默认是 OFF(尤其高并发写场景常被手动关),而 8.0 默认为 ON。它和 innodb_lock_wait_timeout 完全无关——后者只管“等锁超时”,前者才是真正在做死锁图遍历和主动回滚。

常见错误现象:
升级后错误日志里密集出现死锁,但业务逻辑没改;
同一组表、相同 WHERE 条件反复出现在不同事务的 HELD LOCKS 和 WAITING FOR THIS LOCK TO BE GRANTED 中;
事务回滚后应用重试,又立刻触发新死锁。

  • 别急着关 innodb_deadlock_detect:关掉它只会让问题更隐蔽,最终表现为连接堆积、响应延迟、甚至事务卡死
  • 检查是否真有循环等待:用 SHOW ENGINE INNODB STATUS\G 看 LATEST DETECTED DEADLOCK 区块,确认两个事务是否一个持有 A 表锁等待 B 表,另一个反之
  • 如果确实只是“误报”(极少见),可临时关掉: SET GLOBAL innodb_deadlock_detect = OFF,但必须配套监控 INFORMATION_SCHEMA.INNODB_TRX 中长期未提交事务

死锁日志里反复出现相同表和索引?说明加锁顺序不一致

死锁本质是多个事务以不同物理顺序访问同一组行。比如事务 A 先 UPDATE t1 WHERE id = 1 再 UPDATE t2 WHERE order_no = 'xxx',事务 B 反过来先 t2 后 t1;或者批量更新时,WHERE id IN (3,1,2) 和 WHERE id IN (2,3,1) 导致加锁顺序天然不同。

使用场景:
转账、库存扣减、优惠券核销等高频并发更新热点行;
ORM 自动生成的 IN 列表未排序;
分页查询 + 更新混合操作(如先查再按 ID 更新)。

  • 统一 ID 排序:应用层生成 SQL 前对参数列表 ORDER BY id,哪怕只更新一行也强制加 ORDER BY id ASC
  • 避免 ORM 自动拼 IN:禁用 MyBatis 的 <foreach></foreach> 无序遍历,改用预排序集合
  • 热点行加锁强制顺序:对账户余额类场景,用 SELECT ... FOR UPDATE ORDER BY id ASC,即使只锁一行也生效

升级后 sys.innodb_lock_waits 查询变慢甚至阻塞?MDL 锁行为已变

MySQL 8.0 中 sys.innodb_lock_waits 不再是纯视图,它底层依赖 performance_schema.data_locks 和 data_lock_waits,读取时会申请 MDL 锁。如果此时恰有 DDL(如 ALTER TABLE)在执行,监控脚本就会卡在 Waiting for table metadata lock,拖慢连接池,间接推高锁等待和死锁感知密度。

MySQL
MySQL

编写正确的MySQL查询,避免字符集、索引和锁方面的常见陷阱。

下载

容易踩的坑:
运维脚本每 5 秒轮询 sys.innodb_lock_waits;
未限制 lock_wait_timeout,导致监控连接长时间挂起;
DDL 与业务高峰重叠,放大阻塞效应。

  • 改用轻量替代方案:直接查 INFORMATION_SCHEMA.INNODB_TRX + INNODB_LOCKS(8.0.29+ 已移除,需降级兼容)或 performance_schema.data_locks(注意权限)
  • 设好元数据锁超时:SET SESSION lock_wait_timeout = 10,避免监控自己变成阻塞源
  • DDL 尽量避开业务高峰,并确认 metadata_locks_cache_size 足够(默认 1024,高并发建议调至 2048)

为什么优化索引顺序能直接降低死锁频率

索引字段顺序决定执行计划是否走索引、锁多少行。例如联合索引 (pool_id, identifier, status),若 identifier 允许为 NULL,且查询条件是 WHERE pool_id = ? AND status = ?,InnoDB 可能无法跳过中间字段,最终只用到 pool_id 前缀,引发大范围间隙锁(X locks gap before rec),多个事务锁集重叠概率飙升。

性能影响:
没走索引的 UPDATE 会全表扫描加 X 锁,锁行数从几行涨到几千行;
间隙锁范围扩大后,INSERT/UPDATE 邻近值极易冲突;
不同事务因执行路径不同(索引选择差异),加锁顺序天然分裂。

  • 高频等值字段放最左:如总按 pool_id 和 status 查询,建 (pool_id, status, is_redeemed)
  • 范围查询字段放末尾:created_at > ? 必须放在联合索引最后,否则后续字段失效
  • 验证是否生效:开 innodb_print_all_deadlocks = ON,比对死锁日志中 lock_mode 是否从 X locks gap before rec 变成 X locks rec but not gap

真正难处理的不是参数调整,而是那些 SELECT FOR UPDATE 后忘了 COMMIT 的僵尸事务——它们在 5.7 下可能“侥幸存活”,在 8.0 下会被快速暴露、连锁拖垮。查 INFORMATION_SCHEMA.INNODB_TRX 里 trx_started 时间过早的记录,比调任何参数都管用。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

mysql mysql报错 mysql 8.0

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
mysql修改数据表名
mysql修改数据表名

MySQL修改数据表:1、首先查看数据库中所有的表,代码为:‘SHOW TABLES;’;2、修改表名,代码为:‘ALTER TABLE 旧表名 RENAME [TO] 新表名;’。php中文网还提供MySQL的相关下载、相关课程等内容,供大家免费下载使用。

2023.06.20

2013

6

MySQL创建存储过程
MySQL创建存储过程

存储程序可以分为存储过程和函数,MySQL中创建存储过程和函数使用的语句分别为CREATE PROCEDURE和CREATE FUNCTION。使用CALL语句调用存储过程智能用输出变量返回值。函数可以从语句外调用(通过引用函数名),也能返回标量值。存储过程也可以调用其他存储过程。php中文网还提供MySQL创建存储过程的相关下载、相关课程等内容,供大家免费下载使用。

2023.06.21

1239

5

mongodb和mysql的区别
mongodb和mysql的区别

mongodb和mysql的区别:1、数据模型;2、查询语言;3、扩展性和性能;4、可靠性。本专题为大家提供mongodb和mysql的区别的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.18

735

5

mysql密码忘了怎么查看
mysql密码忘了怎么查看

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS 应用软件之一。那么mysql密码忘了怎么办呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.19

2652

5

mysql创建数据库
mysql创建数据库

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS 应用软件之一。那么mysql怎么创建数据库呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

2023.07.25

4388

4

mysql默认事务隔离级别
mysql默认事务隔离级别

MySQL是一种广泛使用的关系型数据库管理系统,它支持事务处理。事务是一组数据库操作,它们作为一个逻辑单元被一起执行。为了保证事务的一致性和隔离性,MySQL提供了不同的事务隔离级别。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2023.08.08

1039

3

sqlserver和mysql区别
sqlserver和mysql区别

SQL Server和MySQL是两种广泛使用的关系型数据库管理系统。它们具有相似的功能和用途,但在某些方面存在一些显著的区别。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.08.11

4651

4

mysql忘记密码
mysql忘记密码

MySQL是一种关系型数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。那么忘记mysql密码我们该怎么解决呢?php中文网给大家带来了相关的教程以及其他关于mysql的文章,欢迎大家前来学习阅读。

2023.08.14

4182

7

mysql事务隔离级别
mysql事务隔离级别

mysql规范中定义了四种事务隔离级别,不同的隔离级别对事务的处理有所不同。本专题为大家提供mysql事务隔离级别相关的文章内容,大家可以免费体验。

2023.08.16

5414

11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL vs MySQL
PostgreSQL vs MySQL

共1课时 | 177人学习

使用phpenv集成环境安装极致CMS
使用phpenv集成环境安装极致CMS

共2课时 | 282人学习