MySQL故障排查与优化

一、MySQL 故障快速定位(5 分钟定位根因)

1. 先看整体状态(最关键)

sql

复制代码
-- 查看 MySQL 整体运行状态
SHOW STATUS;
-- 精简版:只看关键指标
SHOW STATUS LIKE '%Threads%';
SHOW STATUS LIKE '%Queries%';
SHOW STATUS LIKE '%Slow%';

重点看 3 个值:

  • Threads_connected:当前连接数(太高 = 连接爆了)
  • Threads_running正在执行的查询数(>10 基本就堵了)
  • Slow_queries:慢查询数量(>0 说明有慢 SQL)

2. 查看正在执行的 SQL(定位卡死 / 慢查询)

sql

复制代码
-- 查看所有正在跑的查询(含执行时间)
SHOW FULL PROCESSLIST;

-- 更精准:只看运行超过 1 秒的活跃 SQL
SELECT * FROM information_schema.processlist WHERE time > 1 AND command != 'Sleep';

看到这些直接判定故障:

  • Sending data:SQL 没索引,全表扫描
  • Copying to tmp table:临时表太大,内存不够
  • Locked / Waiting for table metadata lock:表被锁死
  • Sleep 大量连接:代码没关闭连接,连接池泄露

3. 查看慢查询日志(必开!)

sql

复制代码
-- 临时开启慢查询(重启失效)
SET GLOBAL slow_query_log = 1;
SET GLOBAL long_query_time = 1;  -- 超过 1 秒就算慢查询
SET GLOBAL log_queries_not_using_indexes = 1;  -- 记录没走索引的 SQL

慢查询日志是排查所有性能问题的核心


4. 查看锁等待(表卡死、更新失败)

sql

复制代码
-- 查看 InnoDB 锁等待
SELECT * FROM information_schema.innodb_locks;
SELECT * FROM information_schema.innodb_lock_waits;

常见锁问题:

  • 长事务不提交 → 锁不释放
  • 无索引更新 → 行锁变表锁
  • DDL(alter table)→ 整表元数据锁死

5. 查看主从延迟(主从同步故障)

sql

复制代码
SHOW SLAVE STATUS\G

看两个字段:

  • Seconds_Behind_Master:延迟秒数
  • Slave_SQL_Running: No:SQL 线程挂了(数据冲突 / 权限问题)

二、MySQL 性能优化(从易到难,直接照做)

1. SQL 优化(80% 问题都在这)

① 必做:给 SQL 加索引

sql

复制代码
-- 查看 SQL 是否走索引
EXPLAIN SELECT * FROM user WHERE phone = '13800138000';

看到 type = ALL 就是全表扫描,必须加索引:

sql

复制代码
CREATE INDEX idx_phone ON user(phone);
② 禁止这些烂 SQL
  • SELECT *
  • LIKE '%keyword%' 左模糊(不走索引)
  • WHERE 1=1 无索引条件
  • 大表 JOIN 无索引
  • ORDER BY / GROUP BY 无索引
③ 分页优化

sql

复制代码
-- 坏:越往后越慢
SELECT * FROM table LIMIT 100000,20;

-- 好:延迟关联,只查主键
SELECT * FROM table t
JOIN (SELECT id FROM table ORDER BY id LIMIT 100000,20) AS tmp
ON t.id = tmp.id;

2. 连接数优化(连接爆、Too many connections)

sql

复制代码
-- 查看最大连接数
SHOW VARIABLES LIKE 'max_connections';

-- 调整(my.cnf)
max_connections = 2000
wait_timeout = 600
interactive_timeout = 600

原因: 代码连接池没释放、Sleep 连接太多。


3. InnoDB 缓冲池优化(内存优化)

最核心配置:

plaintext

复制代码
innodb_buffer_pool_size = 物理内存的 50%~70%
  • 32G 内存 → 设 20G
  • 64G 内存 → 设 40G

作用:把热数据放内存,磁盘 IO 瞬间下降


4. 临时表 & 排序优化

plaintext

复制代码
tmp_table_size = 256M
max_heap_table_size = 256M
sort_buffer_size = 2M
join_buffer_size = 2M

避免 Using temporaryUsing filesort


5. 日志优化(减少磁盘 IO)

plaintext

复制代码
innodb_flush_log_at_trx_commit = 2 (主从架构推荐)
sync_binlog = 1000

能大幅降低磁盘 IO,提升写入速度。


6. 表结构优化

  • INT 不用 VARCHAR 存数字
  • 禁止 TEXT/BLOB 频繁查询
  • 大字段拆表
  • 时间用 DATETIMETIMESTAMP
  • 尽量用 NOT NULL

三、最常见 6 大故障 + 解决方案

1. CPU 100%

原因: 无索引 SQL、大量排序、全表扫描解决:

  1. SHOW FULL PROCESSLIST 找到慢 SQL
  2. EXPLAIN 加索引
  3. 杀掉烂 SQL

2. 连接数爆了

原因: 代码连接泄露、连接池配置错误解决:

  1. 杀掉 Sleep 长连接
  2. 调整 max_connections
  3. 修复应用连接池

3. 磁盘 IO 100%

原因: 缓冲池太小、大量随机 IO、大事务解决:

  1. 调大 innodb_buffer_pool_size
  2. 优化慢 SQL
  3. 关闭不必要的日志

4. 表卡死、更新不动

原因: 长事务、MDL 锁、无索引更新解决:

  1. 查看锁等待
  2. 杀掉长事务
  3. 给更新条件加索引

5. 主从延迟巨大

原因: 从库单线程回放、大事务、无索引解决:

  1. 开启并行复制
  2. 拆大事务
  3. 从库也加索引

6. MySQL 突然宕机

原因: OOM、磁盘满、断电解决:

  1. 看系统日志 /var/log/messages
  2. 看 MySQL 错误日志 error.log
  3. 检查磁盘空间 df -h

四、企业级巡检命令(直接复制用)

sql

复制代码
-- 1. 查看活跃连接
SHOW FULL PROCESSLIST;

-- 2. 查看慢查询数量
SHOW STATUS LIKE 'Slow_queries';

-- 3. 查看 InnoDB 状态
SHOW ENGINE INNODB STATUS;

-- 4. 查看缓存命中率(>95% 正常)
SHOW STATUS LIKE 'Innodb_buffer_pool_read%';

-- 5. 查看表锁 contention
SHOW STATUS LIKE 'Table_locks%';

五、最佳实践总结

  1. 慢查询日志必须永久开启
  2. 所有查询必须走索引
  3. 禁止长事务(<5 秒)
相关推荐
圣光SG2 小时前
Java类与对象及面向对象基础核心详细笔记
java·前端·数据库
2601_949818092 小时前
LangChain-08 Query SQL DB 通过GPT自动查询SQL
数据库·sql·langchain
ytttr8732 小时前
C# 读取数据库表结构工具设计与实现
开发语言·数据库·c#
白露与泡影2 小时前
从 BIO 到 epoll:高并发 I/O 模型演进与本质分析
java·服务器·数据库
知识分享小能手2 小时前
MongoDB入门学习教程,从入门到精通,MongoDB副本集的核心机制(11)
数据库·学习·mongodb
一 乐2 小时前
剧场管理系统|基于springboot + vue剧场管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·剧场管理系统
战族狼魂2 小时前
AI 全程聊天式交互,自动修复错误--撸了一个中英多语言电商独立站,基于SpringBoot+React+MySQL 可Docker一键部署
spring boot·mysql·react.js
阿坤带你走近大数据2 小时前
Oracle里的MINUS是什么
数据库·oracle
佩亚诺余项.2 小时前
SQL Server 系统视图深度应用:批量检索含关键字的存储过程与数据表字段
数据库