MySQL故障排查与优化

一、故障排查概述

1.1 故障排查方法论

python

复制代码
故障排查流程 = [
    "1. 发现问题:监控告警、用户反馈、性能下降",
    "2. 收集信息:错误日志、慢查询、系统状态",
    "3. 分析定位:确定问题范围、复现条件",
    "4. 制定方案:评估影响、选择解决方案",
    "5. 执行修复:备份数据、执行操作、验证结果",
    "6. 复盘总结:记录原因、优化预防、更新文档"
]

1.2 常用诊断工具

工具 用途 命令示例
SHOW PROCESSLIST 查看当前连接 SHOW FULL PROCESSLIST;
SHOW ENGINE INNODB STATUS InnoDB状态 SHOW ENGINE INNODB STATUS\G
PERFORMANCE_SCHEMA 性能监控 SELECT * FROM sys.schema_table_statistics;
pt-query-digest 慢查询分析 pt-query-digest slow.log
mysqldumpslow 慢查询摘要 mysqldumpslow -s t -t 10 slow.log
dmesg 系统日志 `dmesg

二、连接问题排查

2.1 无法连接MySQL

bash

复制代码
# 1. 检查MySQL服务状态
systemctl status mysql
ps aux | grep mysqld

# 2. 检查端口监听
netstat -tlnp | grep 3306
ss -tlnp | grep 3306

# 3. 检查防火墙
iptables -L -n | grep 3306
firewall-cmd --list-all
ufw status

# 4. 检查最大连接数
mysql -u root -p -e "SHOW VARIABLES LIKE 'max_connections';"
mysql -u root -p -e "SHOW STATUS LIKE 'Threads_connected';"

# 5. 检查连接超时设置
mysql -u root -p -e "SHOW VARIABLES LIKE '%timeout%';"

2.2 连接数过多

sql

复制代码
-- 查看当前连接
SHOW PROCESSLIST;
SHOW FULL PROCESSLIST;

-- 按状态统计连接数
SELECT state, COUNT(*) FROM information_schema.PROCESSLIST GROUP BY state;

-- 按用户统计连接数
SELECT user, COUNT(*) FROM information_schema.PROCESSLIST GROUP BY user;

-- 按主机统计连接数
SELECT SUBSTRING_INDEX(host, ':', 1) AS ip, COUNT(*) 
FROM information_schema.PROCESSLIST 
GROUP BY ip ORDER BY COUNT(*) DESC;

-- 杀掉特定连接
KILL connection_id;
KILL QUERY connection_id;  -- 只杀掉查询,不断开连接

-- 批量杀掉特定IP的连接
SELECT CONCAT('KILL ', id, ';') 
FROM information_schema.PROCESSLIST 
WHERE host LIKE '192.168.1.100%' 
INTO OUTFILE '/tmp/kill.sql';
SOURCE /tmp/kill.sql;

2.3 Too many connections 错误

sql

复制代码
-- 临时增加最大连接数
SET GLOBAL max_connections = 500;

-- 永久配置(my.cnf)
[mysqld]
max_connections = 500
max_connect_errors = 100000
back_log = 300  # 连接队列大小

-- 减少空闲连接超时
SET GLOBAL wait_timeout = 600;
SET GLOBAL interactive_timeout = 600;

-- 查看连接复用情况
SHOW STATUS LIKE 'Threads%';
-- Threads_cached: 缓存的线程数
-- Threads_connected: 当前连接数
-- Threads_created: 创建的线程数(应尽量接近Threads_connected)

三、性能问题排查

3.1 慢查询分析

sql

复制代码
-- 1. 开启慢查询日志
SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 2;  -- 超过2秒记录
SET GLOBAL log_queries_not_using_indexes = ON;

-- 查看慢查询配置
SHOW VARIABLES LIKE 'slow_query%';
SHOW VARIABLES LIKE 'long_query_time';

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

-- 3. 分析当前慢查询
SELECT * FROM mysql.slow_log ORDER BY start_time DESC LIMIT 10;

3.2 使用EXPLAIN分析查询

sql

复制代码
-- EXPLAIN输出字段说明
EXPLAIN SELECT * FROM students WHERE age > 18;

-- 关键字段含义
-- id: 查询执行顺序
-- select_type: 查询类型(SIMPLE/PRIMARY/SUBQUERY/DERIVED/UNION)
-- table: 查询的表
-- type: 访问类型(性能从好到差:system > const > eq_ref > ref > range > index > ALL)
-- possible_keys: 可能使用的索引
-- key: 实际使用的索引
-- key_len: 索引使用的字节数
-- ref: 索引比较的列
-- rows: 预估扫描的行数
-- Extra: 额外信息(Using index/Using where/Using temporary/Using filesort)

-- 详细分析(MySQL 8.0+)
EXPLAIN ANALYZE SELECT * FROM students WHERE age > 18;

3.3 常见慢查询优化

sql

复制代码
-- 1. 索引失效的情况
-- 避免在索引列上使用函数
-- 坏
SELECT * FROM students WHERE YEAR(created_at) = 2024;
-- 好
SELECT * FROM students WHERE created_at BETWEEN '2024-01-01' AND '2024-12-31';

-- 避免隐式类型转换
-- 坏(phone是varchar)
SELECT * FROM students WHERE phone = 13800138000;
-- 好
SELECT * FROM students WHERE phone = '13800138000';

-- 避免使用LIKE以通配符开头
-- 坏
SELECT * FROM students WHERE name LIKE '%三';
-- 好
SELECT * FROM students WHERE name LIKE '张%';

-- 2. 优化分页查询
-- 坏(大偏移量)
SELECT * FROM students ORDER BY id LIMIT 100000, 20;
-- 好(使用游标)
SELECT * FROM students WHERE id > 100000 ORDER BY id LIMIT 20;

-- 3. 优化子查询
-- 坏
SELECT * FROM students WHERE class_id IN (SELECT id FROM classes WHERE grade = '高一');
-- 好
SELECT s.* FROM students s JOIN classes c ON s.class_id = c.id WHERE c.grade = '高一';

-- 4. 优化COUNT查询
-- 坏(统计所有行)
SELECT COUNT(*) FROM students;
-- 好(使用近似值)
SELECT TABLE_ROWS FROM information_schema.tables WHERE table_name = 'students';

3.4 锁问题排查

sql

复制代码
-- 1. 查看当前锁等待
SELECT * FROM information_schema.INNODB_TRX;      -- 当前事务
SELECT * FROM information_schema.INNODB_LOCKS;    -- 当前锁
SELECT * FROM information_schema.INNODB_LOCK_WAITS; -- 锁等待关系

-- 2. 查询锁等待详情(MySQL 8.0)
SELECT * FROM performance_schema.data_locks;
SELECT * FROM performance_schema.data_lock_waits;

-- 3. 查看死锁信息
SHOW ENGINE INNODB STATUS\G
-- 查找 "LATEST DETECTED DEADLOCK" 部分

-- 4. 杀掉阻塞的事务
SELECT trx_mysql_thread_id FROM information_schema.INNODB_TRX 
WHERE trx_state = 'RUNNING' AND trx_started < NOW() - INTERVAL 60 SECOND;

-- 5. 查看表锁
SHOW OPEN TABLES WHERE In_use > 0;

-- 6. 查看元数据锁
SELECT * FROM performance_schema.metadata_locks;

四、复制问题排查

4.1 复制延迟

sql

复制代码
-- 1. 查看复制延迟
SHOW SLAVE STATUS\G
-- 关注字段:Seconds_Behind_Master

-- 2. 查看复制线程状态
SHOW PROCESSLIST;
-- 查看 Slave_IO_Running 和 Slave_SQL_Running 线程

-- 3. 开启并行复制
-- 配置文件中设置
slave_parallel_workers = 4
slave_parallel_type = LOGICAL_CLOCK

-- 动态调整
SET GLOBAL slave_parallel_workers = 4;
STOP SLAVE SQL_THREAD;
START SLAVE SQL_THREAD;

-- 4. 调整从库刷盘策略
SET GLOBAL sync_relay_log = 0;
SET GLOBAL sync_relay_log_info = 0;

-- 5. 查看复制延迟原因
SELECT * FROM performance_schema.replication_applier_status_by_worker\G

4.2 复制中断

sql

复制代码
-- 1. 查看错误信息
SHOW SLAVE STATUS\G
-- 查看 Last_Errno 和 Last_Error

-- 2. 跳过错误
-- 跳过1个错误
STOP SLAVE;
SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;
START SLAVE;

-- 3. 使用GTID跳过错误
STOP SLAVE;
SET GTID_NEXT = 'uuid:transaction_id';
BEGIN; COMMIT;
SET GTID_NEXT = 'AUTOMATIC';
START SLAVE;

-- 4. 跳过特定错误(配置文件中)
slave-skip-errors = 1062,1032,1053

-- 5. 重建复制
STOP SLAVE;
RESET SLAVE ALL;
CHANGE MASTER TO ...;
START SLAVE;

4.3 主从数据不一致

bash

复制代码
# 1. 使用pt-table-checksum检查差异
pt-table-checksum --user=root --password=pass \
    --host=192.168.1.100 --databases=school \
    --replicate=checksum.checksums

# 2. 使用pt-table-sync修复
pt-table-sync --execute --sync-to-master \
    --user=root --password=pass h=192.168.1.101

# 3. 手动修复
# 从主库导出问题表
mysqldump -u root -p school students > students.sql
# 在从库导入
mysql -u root -p school < students.sql
相关推荐
私人珍藏库3 小时前
[Android] 后台视频录制 FadCam v3.0.1
android·app·工具·软件·多功能
Z_Wonderful4 小时前
在 **Next.js** 中使用 `mysql2` 连接 MySQL 数据库并查询 `xxx` 表的数据
android·数据库
FirstFrost --sy4 小时前
MySql 内外连接
android·数据库·mysql
激昂网络4 小时前
在Ubuntu 24.04上编译T527 Android系统:遇到的几个问题及解决方法
android·linux·ubuntu
卤炖阑尾炎4 小时前
MySQL 主从复制与读写分离:从原理到实战全解析
mysql·adb
ego.iblacat4 小时前
MySQL 高可用
数据库·mysql·adb
李艺为4 小时前
android客制开发之DevCheck检测CPU核心作假
android
hnlgzb4 小时前
LiveData和MutableLiveData都是什么?有什么区别?都是在什么情况下用?
android
Calebbbbb4 小时前
使用 Android Emulator 针对 AOSP 单测编译运行并检查覆盖率的完整实践
android·linux·安卓