MySQL 故障排查
覆盖 MySQL 所有常见故障场景,包含 定位流程、必查命令、根因分析、修复方法。
结构按 从现象 -> 分析 -> 诊断 -> 解决 排列,可直接拿来当运维手册使用。
MySQL 的所有故障,基本都可以归为五大类:
- 性能瓶颈(CPU / IO / 内存 / 连接数)
- 锁问题(死锁、长事务、等待行锁 / 元数据锁)
- 资源耗尽(磁盘满 / redo 满 / undo 膨胀)
- 复制异常(主从延迟、复制中断、GTID 冲突)
- 配置错误 / 参数不当
排查总顺序(必须遵守):
线程 -> 锁 -> 慢 SQL -> 资源 -> 系统 -> 配置 -> 日志
- CPU 接近 100%
- Threads_running 持续高
- 查询响应时间暴涨
SHOW PROCESSLIST;
高概率看到:
- “Sending data”
- “Copying to tmp table”
- “Waiting for table metadata lock”
SELECT * FROM performance_schema.events_statements_current LIMIT 10;
SELECT * FROM information_schema.innodb_locks;
SELECT * FROM sys.statement_analysis
ORDER BY total_cpu_time DESC LIMIT 10;
- 缺索引引发全表扫描
- 大量复杂 JOIN
- 全表排序、临时表
- 大事务导致行锁阻塞
- 元数据锁 MDL 被长事务占用
-
添加索引(最常见解决方案)
-
拆 SQL(避免大查询)
-
Kill 明显卡住的长查询:
KILL <id>; -
在线回收元数据锁:
KILL CONNECTION <trx_holding_MDL>;
- 磁盘写吞吐暴涨
- fsync 延迟高
- 存储抖动导致 TPS 降低
SHOW GLOBAL STATUS LIKE 'innodb_data_%';
SHOW GLOBAL STATUS LIKE 'innodb_os_log_fsyncs';
SHOW ENGINE INNODB STATUS\G;
关注:
Log sequence number
Checkpoint age
Checkpoint age 接近 redo log 大小 ⇒ MySQL 强制落盘 -> IO 爆炸
- redo log 太小
- buffer pool 太小
- 性能不足的存储(非 SSD / SATA)
- 大量随机写
- 调大 redo log:
innodb_log_file_size = 2G
- 升级 SSD
- 增加 buffer pool
- 优化写热点表结构
SELECT * FROM information_schema.innodb_trx;
SELECT * FROM information_schema.innodb_locks;
SELECT * FROM information_schema.innodb_lock_waits;
SHOW ENGINE INNODB STATUS\G;
- 多事务抢同一行
- 更新顺序不一致
- 索引缺失导致锁范围扩大
- 大事务长时间不提交
- 拆小事务
- 增加索引
- 将频繁写热点表分片
- 改成乐观锁(version 字段)
- undo 表空间暴涨
- 磁盘变满
- 复制延迟加剧
- Checkpoint age 长期不回收
SELECT * FROM information_schema.innodb_trx
ORDER BY trx_started LIMIT 5;
- 应用层忘记 commit
- Hibernate / JPA 开启自动事务
- MySQL 客户端 idle in transaction
-
Kill:
KILL <trx_mysql_thread_id>; -
改应用(根因永远在应用)
- MySQL 崩溃
- 无法写入数据
- undo / redo 巨大
df -h
检查 undo 表空间
SELECT tablespace_name, file_size
FROM information_schema.innodb_tablespaces;
- 长事务
- 大量临时表
- 未清理 binlog
- InnoDB undo 不可回收
-
删除旧 binlog
PURGE BINARY LOGS BEFORE NOW() - INTERVAL 7 DAY; -
终止长事务
-
优化大查询
注意:磁盘满必须立即停 MySQL,否则表空间会损坏。
检查:
SHOW SLAVE STATUS\G;
关注字段:
- Last_IO_Error
- Last_SQL_Error
- Seconds_Behind_Master
常见错误
- 主键冲突
- 行找不到(ROW 模式下)
- relay log 损坏
- GTID 冲突
-
重置复制:
RESET SLAVE ALL; CHANGE MASTER TO …; START SLAVE; -
跳过事务(不推荐):
SET GLOBAL sql_slave_skip_counter=1; -
MGR 修复:
SELECT * FROM performance_schema.replication_group_member_stats;
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_reads';
命中率 < 99% ⇒ buffer pool 太小
- join_buffer / sort_buffer 过大
- 连接数导致内存飙升
- 查询创建巨大临时表
join_buffer_size = 1M
sort_buffer_size = 2M
max_connections = 500
chown -R mysql:mysql /var/lib/mysql
/var/log/mysql/error.log
常见报错:
- 表空间损坏
- redo log 读取失败
- 端口被占用
- 配置文件拼写错误
innodb_force_recovery = 1~6
6 最危险,只用于导出数据。
检查连接数
SHOW GLOBAL STATUS LIKE 'Threads_connected';
查看是否连接泄漏
SHOW PROCESSLIST;
连不上排查三步骤
- MySQL bind-address 是否限制
- 防火墙(iptables / firewalld)
- 密码插件 caching_sha2 vs mysql_native_password
查看:
SHOW ENGINE INNODB STATUS\G;
现象:
- Checkpoint age 接近 redo 大小
- MySQL 卡住、不响应写入
解决:
- 增加 redo 大小:innodb_log_file_size
- 优化热点写表
- 停掉大事务
查看:
Threads_running
innodb_trx / innodb_locks / innodb_lock_waits
sys.statement_analysis
SHOW ENGINE INNODB STATUS
top, vmstat, iostat
SHOW SLAVE STATUS\G;
- 任何问题第一看 Threads_running
- 慢 SQL 永远比配置更重要
- 长事务是 MySQL 最大敌人
- redo / undo 膨胀通常是事务不提交
- MDL 锁经常是 alter table 引起的
- 复制中断大多由主键冲突或 GTID 冲突
- checkpoint age 接近 redo 大小 = IO 爆炸
- 大表不要轻易做全表操作
- 磁盘满 = 必须停 MySQL
- 所有故障排查都离不开 error.log