MySQL InnoDB 存储引擎遇到严重阻塞,导致多个线程在等待信号量(semaphore)超过600秒,最终触发了致命崩溃。具体分析如下:
报错核心信息
-
Semaphore wait has lasted > 600 seconds
InnoDB 中的信号量等待时间超过600秒,说明内部资源竞争严重阻塞,导致线程无法继续。 -
mysqld got signal 6
收到信号6(SIGABRT),通常是程序主动abort(终止)以防止进一步损坏。 -
多个线程长时间等待信号量:
mtr0mtr.cc line 567
等待 387 秒row0ins.cc line 193
等待 399 秒mtr0mtr.cc line 2997
等待 399 秒
-
Assertion failure in file ut0ut.cc line 916
断言失败,表明程序检测到状态不符合预期,可能是内部数据结构不一致。 -
日志提示可能有表空间损坏,建议参考
forcing-innodb-recovery
方案。
可能原因分析
-
严重的内部死锁或资源竞争
多个线程争抢InnoDB内部锁(信号量),长时间未释放。 -
表空间或数据页损坏
报错建议怀疑InnoDB表空间损坏,导致内部状态异常。 -
系统资源瓶颈或IO阻塞
磁盘IO性能异常,导致InnoDB操作阻塞。 -
高并发写入压力
从日志中看到写入速度(inserts/s)高达85,且读写量巨大,可能导致锁争用严重。 -
InnoDB Bug
极少数情况下InnoDB内部bug导致死锁或等待。
解决建议
1. 临时启动参数强制恢复(最低等级)
编辑 MySQL 配置文件,添加:
[mysqld]
innodb_force_recovery=1
然后启动 MySQL。这个参数可以从1逐步增加到6(越高恢复越强硬,风险越大)用来导出数据。
2. 导出数据,重建表空间
- 使用
innodb_force_recovery
启动后,尽快导出所有重要数据(用mysqldump
或其他工具)。 - 停止 MySQL,删除 InnoDB 表空间文件(如 ibdata1,ib_logfile*,和相关表的.ibd 文件)。
- 重新初始化 MySQL 数据目录,导入数据。
3. 检查磁盘和系统状态
- 检查磁盘IO负载、SMART状态,确认没有硬件故障。
- 查看系统是否存在内存压力、CPU飙高等资源瓶颈。
4. 优化应用层
- 减少写入压力,尽量分批处理。
- 检查事务是否长时间未提交,导致锁阻塞。
5. 更新MySQL版本
- 如果是已知InnoDB版本Bug,考虑升级到稳定版本。
你可以优先执行的步骤
-
备份当前数据目录(防止二次破坏)。
-
尝试用
innodb_force_recovery=1
启动,导出数据。 -
分析导出是否正常,重点导出出错的表。
-
重建环境,恢复导出数据。
-
评估应用写入压力、SQL是否存在长事务。
下一不:提供更多的信息:
- MySQL版本号
- 具体执行的操作(比如什么写入/更新/删除操作)
- 当前系统负载情况