MySQL Semaphore wait has lasted使用详解
目录
- 1. 理解信号量(Semaphore)和等待的背景
- 2. 收集环境与上下文信息
- 3. 查看mysql错误日志和InnoDB状态
- a. 错误日志中的关键信息
- b. 通过SHOW ENGINE INNODB STATUS\G观察
- 4. 结合源码行号,定位具体阻塞点
- 5. 重点排查方向
- 5.1 长事务导致锁资源占用
- 5.2 高并发写入导致缓冲池争用
- 5.3 磁盘IO瓶颈
- 5.4 表空间或数据页损坏
- 6. 其他诊断技巧
- 6.1 启用详细InnoDB调试日志
- 6.2 使用性能Schema定位锁等待
- 7. 解决建议总结
- 8. 典型诊断命令举例
- 总结
MySQL 5.7.19 版本出现 Semaphore wait has lasted > 600 seconds
错误,意味着 InnoDB 内部某些线程等待信号量超过了10分钟,导致数据库挂起崩溃。
针对这个问题,排查和定位的思路及步骤如下:
1. 理解信号量(Semaphore)和等待的背景
- InnoDB 通过信号量机制保护共享资源访问,例如缓冲池页、锁、事务信息等。
- 长时间等待信号量一般是死锁、资源竞争、内部异常或IO瓶颈导致的。
- 错误日志中会列出等待信号量的线程堆栈位置(源码文件 + 行号),有助定位是哪类资源阻塞。
2. 收集环境与上下文信息
MySQL版本:
- 5.7.19,是较早的5.7版本,InnoDB还有一些已修复的问题,建议考虑升级。
服务器硬件与资源状况:
- CPU、内存利用率
- 磁盘IO状况(IOPS、延迟)
数据库负载情况编程:
- 并发连接数
- 读写比例
- 是否有长事务/大事务
具体业务场景:
- 当时运行什么SQL,是否有大量INSERT/UPDATE/DELETE
- 是否有DDL操作(alter、drop)
3. 查看MySQL错误日志和InnoDB状态
a. 错误日志中的关键信息
确认报错线程对应的源码文件和行号:
mtr0mtr.cc
,row0ins.cc
等,分别代表:
mtr0mtr.cc
:多版本事务相关管理(Mini-transaction)row0ins.cc
:行插入相关代码
这些提示可能表明在插入操作中出现了阻塞。
b. 通过SHOW ENGINE INNODB STATUS\G观察
- 锁等待情况(LATEST DETECTED DEADLOCK)
- 当前活跃事务列表
- semaphore wait 信息(
SEMAPHORE WAIT
块) - 主线程或阻塞线程的详细信息
4. 结合源码行号,定位具体阻塞点
可以通过查看5.7.19版本源码对应文件(MySQL官方github或者源码包)定位:
mtr0mtr.cc line 567
涉及Mini-transaction相关锁等待,可能是InnoDB内部的metadata锁或缓冲池访问竞争。
row0ins.cc line 193
插入行时等待信号量,可能是插入缓冲区竞争或插入锁等待。
5. 重点排查方向
5.1 长事务导致锁资源占用
SHOW PROCESSLIST
看是否存在长时间未提交的事务。INFORMATION_SCHEMA.INNODB_TRX
查看当前活动事务。- 关闭长事务或者合理设置事务超时。
5.2 高并发写入导致缓冲池争用
高并发大批量写入,缓冲池页锁争用严重。
调整 InnoDB 参数,如:
innodb_thread_concurrency
innodb_lock_wait_timeout
innodb编程客栈_buffer_pool_size
(确保足够大,避免频繁刷盘)
5.3 磁盘IO瓶颈
- 使用系统工具(
IOStat
,vmstat
)检查磁盘负载和延迟。 - 高IO延迟会导致InnoDB锁等待。
5.4 表空间或数据页损坏
- 使用
CHECK TABLE
检查相关表。 - 参考错误日志是否有提示页损坏。
6. 其他诊断技巧
6.1 启用详细InnoDB调试日志
启动MySQL时添加:
[androidmysqld] innodb_print_all_deadlocks=ON innodb_lock_wait_timeout=50
查看死锁详细信息。
6.2 使用性能Schempythona定位锁等待
- 查询
performance_schema.data_locks
和performance_schema.data_lock_waits
,定位锁资源。
7. 解决建议总结
问题点 | 排查方法 | 解决措施 |
---|---|---|
长事务占用锁 | SHOW PROCESSLIST, INNODB_TRX | 关闭或优化长事务,合理拆分事务 |
高并发写压力大 | 观察缓冲池争用,线程锁等待 | 优化参数,分批写入,升级版本 |
磁盘IO瓶颈 | iostat, vmstat | 优化存储,使用SSD,提高IO性编程能 |
表空间或页损坏 | CHECK TABLE, innodb_force_recovery尝试 | 恢复数据,导出备份,重建表空间 |
InnoDB版本缺陷 | 官方Bug报告,源码分析 | 升级MySQL版本到最新稳定版 |
8. 典型诊断命令举例
-- 查看当前阻塞事务 SELECT * FROM information_schema.innodb_trx\G; -- 查看当前等待锁的线程 SELECT * FROM performance_schema.data_locks WHERE LOCK_STATUS='WAITING'; -- 查看进程列表,看长时间执行的SQL SHOW FULL PROCESSLIST; -- 查看死锁日志(在错误日志中) -- 或启用 innodb_print_all_deadlocks=ON 后捕获
总结
先从当前活跃事务和锁等待入手排查。
结合InnoDB状态和系统IO性能分析瓶颈。
若怀疑数据损坏,尝试使用 innodb_force_recovery
。
5.7.19版本较老,建议升级至5.7较新版本,或者8.0版本,获得更多稳定性和bug修复。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。
精彩评论