一、故障排查核心原则与准备工作
1.1 核心原则
先恢复服务,再定位根因;先排查硬件/环境,再排查软件/配置;先排查全局问题,再排查局部问题(如单表、单SQL)。
排查过程中做好记录(故障现象、操作步骤、执行结果),避免误操作扩大故障范围,严禁在生产环境随意执行高危命令(如drop、alter等)。
1.2 准备工作
-
工具准备:MySQL客户端(mysql、navicat)、监控工具(Prometheus+Grafana、Zabbix)、日志查看工具(tail、less、grep)、性能分析工具(explain、show profile、pt-query-digest)。
-
权限准备:确保拥有MySQL的super、process、select权限,可查看日志、进程、表结构等。
-
环境信息收集:MySQL版本、操作系统版本、服务器配置(CPU、内存、磁盘)、数据库架构(主从、集群)、当前业务量。
二、常见故障排查(按故障类型分类)
2.1 连接类故障(无法连接MySQL)
2.1.1 故障现象
客户端报错:"Can't connect to MySQL server on 'xxx' (111)"(连接拒绝)、"Lost connection to MySQL server at 'reading initial communication packet'"(连接中断)、"Access denied for user 'xxx'@'xxx' (using password: YES)"(权限拒绝)。
2.1.2 排查步骤
-
检查MySQL服务状态:
systemctl status mysqld(Linux)、net start mysql(Windows),确认服务是否启动。若未启动,查看启动日志(/var/log/mysqld.log)排查启动失败原因(如配置文件错误、端口占用、数据目录权限不足)。 -
检查网络连通性:
ping 数据库IP(检查网络可达)、telnet 数据库IP 端口(默认3306,检查端口是否开放)。若端口不通,排查防火墙(iptables、firewalld)是否拦截,或端口被其他进程占用(netstat -tulnp | grep 3306)。 -
检查MySQL配置:查看my.cnf(Linux)/my.ini(Windows)中的
bind-address(是否限制了连接IP)、port(是否修改了默认端口)、max_connections(是否达到最大连接数)。 -
检查用户权限:登录MySQL(本地登录,如
mysql -u root -p),执行select user,host,password_expired from mysql.user where user='xxx';,确认用户是否存在、host是否允许当前客户端IP、密码是否过期、是否有连接权限(grant all on *.* to 'xxx'@'xxx' identified by 'xxx';授权)。
2.2 查询缓慢故障(SQL执行卡顿)
2.2.1 故障现象
单条SQL执行时间过长(超过1s)、批量查询卡顿、应用接口超时,数据库CPU、IO使用率异常偏高。
2.2.2 排查步骤
-
定位慢SQL:开启慢查询日志(临时开启:
set global slow_query_log=1;,set global long_query_time=1;(超过1s记录)),查看慢查询日志(默认/var/log/mysqld-slow.log),或使用show processlist;查看当前运行的进程,找到状态为"Query"且时间过长的SQL。 -
分析慢SQL:使用
explain分析SQL执行计划,重点关注:-
type:连接类型,优先级从高到低为system > const > eq_ref > ref > range > index > all(all为全表扫描,性能最差)。
-
key:是否使用了索引(NULL表示未使用索引)。
-
rows:预计扫描的行数,行数越多,性能越差。
-
Extra:是否有"Using filesort"(文件排序,需优化)、"Using temporary"(临时表,需优化)。
-
-
排查索引问题:查看表结构(
show create table 表名;),确认是否创建了合适的索引(主键索引、唯一索引、联合索引),索引是否失效(如使用函数、模糊查询%开头、类型不匹配、联合索引顺序错误)。 -
排查表数据量:查看表行数(
select count(*) from 表名;),若数据量过大(百万级以上),需考虑分表、分区,或优化查询条件。
2.3 数据库卡死/宕机故障
2.3.1 故障现象
MySQL服务无响应、客户端无法连接、服务器CPU/内存/IO使用率达到100%,甚至服务器重启。
2.3.2 排查步骤
-
紧急恢复:若服务宕机,先重启MySQL服务(
systemctl restart mysqld),恢复业务后再排查根因;若服务卡死,先执行show processlist;,杀死阻塞进程(kill 进程ID;),优先杀死长时间运行、无意义的查询进程。 -
查看系统日志:Linux查看/var/log/messages(系统日志)、/var/log/mysqld.log(MySQL错误日志),Windows查看事件查看器,排查是否有硬件故障(CPU、内存、磁盘损坏)、系统资源耗尽(内存溢出、磁盘满)。
-
排查磁盘空间:
df -h(Linux)查看磁盘使用率,若磁盘满(超过90%),删除无用日志、临时文件,或扩展磁盘空间;MySQL数据目录(如/var/lib/mysql)满会导致服务卡死,需清理二进制日志(purge binary logs before '2026-04-01 00:00:00';)。 -
排查死锁:执行
show engine innodb status;查看死锁信息,找到死锁的SQL和事务,优化SQL逻辑,避免事务长时间占用资源,或调整事务隔离级别。 -
排查配置问题:查看my.cnf中的内存配置(
innodb_buffer_pool_size、sort_buffer_size、join_buffer_size),若内存配置过高,导致系统内存不足,触发OOM(Out Of Memory),会导致MySQL宕机,需合理调整配置(如innodb_buffer_pool_size建议设置为服务器内存的50%-70%)。
2.4 数据异常故障(丢失、错乱)
2.4.1 故障现象
数据查询不到、数据重复、数据被误删/修改、主从数据不一致。
2.4.2 排查步骤
-
排查操作记录:查看MySQL二进制日志(binary log),执行
show binary logs;,找到对应时间的日志文件,使用mysqlbinlog 日志文件 --start-datetime='xxx' --stop-datetime='xxx'查看操作记录,确认是否有误操作(如delete、update未加条件)。 -
数据恢复:若数据丢失,可通过二进制日志恢复(基于时间点恢复)、备份文件恢复(若有全量备份+增量备份);若主从数据不一致,先停止从库同步(
stop slave;),重新执行全量备份同步,再开启同步(start slave;),查看同步状态(show slave status\G;),确保Slave_IO_Running和Slave_SQL_Running均为Yes。 -
排查事务问题:查看是否有未提交的事务(
select * from information_schema.innodb_trx;),未提交的事务会导致数据不可见,需提交(commit;)或回滚(rollback;)。
三、MySQL优化(分维度优化)
3.1 配置优化(my.cnf核心配置)
核心配置优化(基于Linux系统,根据服务器配置调整),重点关注以下参数:
-
内存配置:
-
innodb_buffer_pool_size:InnoDB缓冲池大小,建议设置为服务器内存的50%-70%,用于缓存表数据和索引,减少磁盘IO。 -
sort_buffer_size:排序缓冲区大小,每个连接独立分配,建议设置为1-4M,避免过大导致内存耗尽。 -
join_buffer_size:连接缓冲区大小,每个连接独立分配,建议设置为1-4M,优化多表连接性能。
-
-
日志配置:
-
slow_query_log=1:开启慢查询日志,便于定位慢SQL。 -
long_query_time=1:设置慢查询阈值(1s),超过该时间的SQL记录到慢查询日志。 -
expire_logs_days=7:设置二进制日志保留时间(7天),自动清理过期日志,避免磁盘满。
-
-
连接配置:
-
max_connections=1000:设置最大连接数,根据业务量调整,避免连接数不足导致无法连接。 -
wait_timeout=600:设置连接超时时间(10分钟),自动关闭空闲连接,释放资源。
-
-
InnoDB优化:
-
innodb_flush_log_at_trx_commit=1:每次事务提交时,将日志写入磁盘,保证数据一致性(牺牲部分性能,适合对数据一致性要求高的场景)。 -
innodb_log_file_size:InnoDB日志文件大小,建议设置为1-2G,减少日志切换频率,提升性能。 -
innodb_file_per_table=1:每个表单独生成一个ibd文件,便于管理和维护,避免单文件过大。
-
3.2 SQL优化(核心优化方向)
3.2.1 索引优化
-
创建合适的索引:主键索引(必填)、唯一索引(用于唯一约束,如手机号、身份证)、联合索引(用于多条件查询,遵循"最左前缀原则",将查询频率高的字段放在前面)。
-
避免索引失效:
-
不使用函数操作索引字段(如
where DATE(create_time) = '2026-04-01',改为where create_time between '2026-04-01 00:00:00' and '2026-04-01 23:59:59')。 -
不使用模糊查询%开头(如
where name like '%张三',改为where name like '张三%',后者可使用索引)。 -
避免索引字段类型不匹配(如字段为int,查询时用字符串匹配,如
where id = '123')。
-
-
定期维护索引:删除无用索引(未被使用的索引,可通过
sys.schema_unused_indexes查看)、优化碎片化索引(optimize table 表名;)。
3.2.2 SQL语句优化
-
避免全表扫描:尽量使用索引查询,避免
select *,只查询需要的字段,减少数据传输量。 -
优化多表连接:尽量使用inner join(内连接),避免left join/right join(外连接),若必须使用外连接,确保关联字段有索引;减少连接表的数量(建议不超过3张表)。
-
避免子查询:子查询效率较低,可改为关联查询(join),如
select * from user where id in (select user_id from order),改为select u.* from user u join order o on u.id = o.user_id。 -
避免批量操作:批量insert、update、delete时,分批次执行(如每次1000条),避免一次性操作导致锁表、服务器压力过大。
-
使用limit限制返回行数:查询时使用
limit,避免返回大量数据(如select * from user limit 100)。
3.3 表结构优化
-
选择合适的数据类型:尽量使用占用空间小的数据类型,如用int代替varchar(存储数字)、用tinyint代替int(存储0-255的数字)、用datetime代替varchar(存储时间),减少磁盘占用和内存消耗。
-
避免字段冗余:不重复存储相同的数据(如用户表和订单表,不重复存储用户名,通过用户ID关联),减少数据更新时的一致性问题。
-
分表分库:当单表数据量超过百万级,查询性能会明显下降,可进行分表(水平分表:按时间、用户ID拆分;垂直分表:将大表拆分为多个小表,按字段拆分);当数据库压力过大,可进行分库(按业务模块拆分)。
-
使用分区表:对于时间范围相关的表(如订单表、日志表),使用分区表(如按月份分区),查询时只扫描对应分区,提升查询效率,便于数据归档。
3.4 服务器与环境优化
-
硬件优化:提升服务器CPU核心数、内存大小,使用SSD磁盘(相比机械硬盘,IO速度提升10倍以上),减少磁盘IO瓶颈。
-
操作系统优化:关闭不必要的服务,释放系统资源;调整内核参数(如调整TCP连接数、IO调度算法),优化网络和磁盘性能。
-
数据库架构优化:搭建主从复制(一主多从),主库负责写操作,从库负责读操作,分担主库压力;搭建集群(如MySQL Cluster、MGR),提升高可用性和并发处理能力。
四、常用排查与优化命令汇总
4.1 基础状态查询命令
-
查看MySQL版本:
select version(); -
查看当前连接数:
show global status like 'Threads_connected'; -
查看最大连接数:
show variables like 'max_connections'; -
查看慢查询日志状态:
show variables like '%slow_query%'; -
查看当前运行进程:
show processlist; -
查看InnoDB状态:
show engine innodb status; -
查看表结构:
show create table 表名; -
查看索引:
show index from 表名;
4.2 性能分析命令
-
分析SQL执行计划:
explain SQL语句; -
查看SQL执行耗时:
set profiling=1;(开启 profiling),执行SQL后,show profiles;(查看所有SQL耗时),show profile for query 进程ID;(查看具体SQL的执行细节)。 -
分析慢查询日志:
pt-query-digest 慢查询日志文件(需安装percona-toolkit工具),生成慢查询统计报告。
4.3 优化操作命令
-
创建索引:
create index 索引名 on 表名(字段名);(普通索引)、create unique index 索引名 on 表名(字段名);(唯一索引)、create index 索引名 on 表名(字段1,字段2);(联合索引)。 -
删除索引:
drop index 索引名 on 表名; -
优化表:
optimize table 表名;(优化表结构和索引,释放碎片空间)。 -
清理二进制日志:
purge binary logs before '2026-04-01 00:00:00'; -
杀死进程:
kill 进程ID;
五、注意事项
-
生产环境禁止直接修改配置文件和执行高危操作,需先在测试环境验证,再灰度发布。
-
定期备份数据(全量备份+增量备份),避免数据丢失,备份后需验证备份文件的可用性。
-
定期监控数据库状态(CPU、内存、IO、连接数、慢查询),建立预警机制,提前发现问题。
-
SQL优化需结合业务场景,不能只追求性能,还要保证数据一致性和业务正确性。
-
定期维护数据库(清理日志、优化索引、检查表结构),避免碎片化和性能退化。
-
遇到复杂故障,优先排查基础问题(服务、网络、磁盘、配置),再深入排查SQL和数据问题,必要时联系MySQL官方支持或专业运维人员。