一、 MySQL 单实例故障排查
当 MySQL 单实例出现问题时,可按以下步骤进行排查:
基础检查:
服务状态 :确认 MySQL 服务是否正在运行 (systemctl status mysql 或 service mysql status)。
网络连接 :检查端口是否监听 (netstat -tuln | grep 3306),防火墙是否开放端口。
连接尝试 :尝试使用命令行客户端 (mysql -u user -p) 或其他工具连接,记录错误信息。
错误日志 :首要查看 MySQL 的错误日志文件 (通常位于 /var/log/mysql/error.log 或 /var/log/mysqld.log),其中记录了启动、运行、关闭过程中的详细错误信息。
资源瓶颈检查:
CPU :使用 top、htop 查看 CPU 使用率,重点关注 %us (用户空间) 和 %sy (内核空间)。如果 MySQL 进程 (mysqld) 占用过高,可能 SQL 效率低或存在锁争用。
内存 :检查系统内存 (free -m) 和 Swap 使用情况。查看 MySQL 内存配置 (innodb_buffer_pool_size, key_buffer_size 等) 是否合理。关注 OOM (内存溢出) 相关的内核日志 (dmesg) 或 MySQL 错误日志。
磁盘 I/O :使用 iostat, iotop 检查磁盘利用率 (%util)、响应时间 (await)。高 I/O 等待可能是慢查询、磁盘性能瓶颈或配置不当 (如 innodb_io_capacity 设置过低) 导致。
磁盘空间 :检查数据目录所在分区的剩余空间 (df -h),避免因磁盘满导致服务异常。
MySQL 内部状态检查:
进程列表 :使用 SHOW PROCESSLIST; 查看当前所有连接的状态,寻找阻塞的查询 (State 如 Locked, Sending data, Sorting result 等耗时操作)。
锁信息 :对于 InnoDB, 使用 SHOW ENGINE INNODB STATUS\G 查看 TRANSACTIONS 和 LATEST DETECTED DEADLOCK 部分,分析事务和死锁情况。
状态变量 :使用 SHOW GLOBAL STATUS; 查看关键指标,如连接数 (Threads_connected, Threads_running)、查询吞吐量 (Queries, Com_select, Com_update 等)、临时表创建 (Created_tmp_disk_tables, Created_tmp_files)、表扫描 (Handler_read%)、InnoDB 缓冲池命中率 (计算 Innodb_buffer_pool_reads / (Innodb_buffer_pool_read_requests + Innodb_buffer_pool_reads) ) 等。
慢查询日志 :检查慢查询日志 (slow_query_log),分析执行时间长的 SQL 语句,结合 EXPLAIN 进行优化。
配置检查 :检查 my.cnf 配置文件是否有误,特别是最近修改过的配置项。
二、 MySQL 主从故障排查 (复制故障)
主从复制故障通常表现为同步延迟 (Seconds_Behind_Master 持续增长或为 NULL) 或复制中断 (Slave_IO_Running/Slave_SQL_Running 为 No)。
查看复制状态:
sql
SHOW SLAVE STATUS\G
关键字段:
Slave_IO_State: I/O 线程当前状态。
Slave_IO_Running: I/O 线程是否运行 (负责获取 Binlog)。
Slave_SQL_Running: SQL 线程是否运行 (负责执行 Binlog)。
Last_IO_Error, Last_SQL_Error: 最后发生的错误信息。
Seconds_Behind_Master: 从库落后主库的秒数 (估算)。
Master_Log_File / Read_Master_Log_Pos: 从库 I/O 线程读取到的主库 Binlog 位置。
Relay_Master_Log_File / Exec_Master_Log_Pos: 从库 SQL 线程执行到的主库 Binlog 位置 (实际同步点)。
Relay_Log_File / Relay_Log_Pos: 从库 Relay Log 位置。
常见问题及排查:
Slave_IO_Running: No:
网络问题:检查主从间网络连通性 (ping, telnet <master_ip> 3306)。
权限问题:确保复制用户 (REPLICATION SLAVE) 在主库存在且密码正确。
主库 Binlog 问题:检查主库 log_bin 是否开启,server_id 是否唯一。
主库文件缺失:如果错误提示找不到 Binlog 文件,可能主库已清理 Binlog,需重建复制。
Slave_SQL_Running: No:
Last_SQL_Error 是关键!常见原因:
从库执行 SQL 失败:主库执行成功的 SQL 在从库执行失败 (如:主键冲突、数据不存在、表结构不一致)。
临时表或变量:某些语句在主库使用临时表或用户变量,在从库重放时环境不同导致失败。
从库有写入:禁止直接写入从库,否则极易导致冲突。
解决办法:根据错误信息分析原因。若可跳过,可尝试 SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; 跳过一个错误事件 (需谨慎),或手动修复数据后重启 SQL 线程 (START SLAVE SQL_THREAD;)。严重不一致时可能需要重建复制。
复制延迟 (Seconds_Behind_Master 高):
从库硬件瓶颈:CPU、内存、磁盘 I/O (尤其是 Relay Log 写入和 SQL 重放) 不足。
大事务/长事务:主库执行一个大事务耗时久,Binlog 传输到从库后,从库执行同样耗时。
从库并行复制能力不足:检查 slave_parallel_workers 配置,适当增加并行线程数 (需考虑服务器资源)。
慢 SQL 在从库重放:主库的慢查询在从库执行同样慢。
网络延迟:主从间网络带宽不足或延迟高。
检查点:Seconds_Behind_Master 的计算方式可能导致瞬时不准确,需结合 Exec_Master_Log_Pos 和主库 SHOW MASTER STATUS; 比较。
复制一致性校验 :定期使用工具 (pt-table-checksum) 检查主从数据一致性。
三、 MySQL 优化
优化是一个持续的过程,需要监控、分析、调整、验证。
硬件方面:
CPU:选择高主频或多核心 CPU (取决于并发查询需求)。
内存 :至关重要。配置足够内存容纳 InnoDB Buffer Pool (通常建议设置为可用物理内存的 70%-80%),减少磁盘 I/O。
磁盘:
类型:首选 SSD (NVMe > SATA SSD) 极大提升 I/O 性能。避免使用普通 HDD。
配置:使用 RAID 10 提高冗余和性能。对于云环境,选择 Provisioned IOPS 磁盘。
文件系统 :如 xfs 或 ext4 (配置 noatime 等选项)。
网络:确保服务器间 (特别是主从、应用与 DB) 有足够带宽和低延迟。
MySQL 配置文件 (my.cnf) 优化:
核心参数:
ini
[mysqld]
# InnoDB 缓冲池大小 (核心中的核心)
innodb_buffer_pool_size = 物理内存的 70%-80% # 例如 64G 内存可设 48G
# 日志相关
innodb_log_file_size = 1G # 增大可减少刷新频率,但恢复时间变长。建议设置多个文件 (innodb_log_files_in_group=2-4),每个 1-4G。
innodb_flush_log_at_trx_commit = 1 # 保证 ACID,安全性最高 (每次提交刷盘)。可设为 2 (每秒刷盘) 或 0 (每秒刷盘且不等待刷盘完成) 以提升性能,但牺牲部分持久性。
# 连接相关
max_connections = 合理值 # 根据应用需求设置,避免过高耗尽资源。监控 `Threads_connected`。
# 其他 InnoDB
innodb_flush_method = O_DIRECT # (Linux) 绕过 OS 缓存,减少双重缓冲。
innodb_io_capacity = 磁盘 IOPS 能力 # 告知 InnoDB 磁盘能力,影响后台刷新速率。SSD 可设 1000-2000。
innodb_io_capacity_max = innodb_io_capacity * 2 # 峰值 IOPS 能力。
# 查询缓存 (MySQL 8.0 已移除,低版本通常建议关闭)
query_cache_type = 0
query_cache_size = 0
# 其他
tmp_table_size / max_heap_table_size = 32M # 控制内存临时表大小,超出转磁盘。根据需求调整。
原则 :根据实际负载 和监控数据调整,避免照搬网上配置。每次修改少量参数,观察效果。
SQL 语句优化:
识别慢查询 :开启并分析慢查询日志 (slow_query_log, long_query_time, log_queries_not_using_indexes)。
使用 EXPLAIN :对慢查询执行 EXPLAIN 或 EXPLAIN FORMAT=JSON 分析执行计划。
关注 type (访问类型,const/eq_ref/ref 较好,index/ALL 差)。
关注 key (使用的索引)。
关注 rows (预估扫描行数)。
关注 Extra (额外信息,如 Using filesort, Using temporary 通常需优化)。
索引优化:
确保 WHERE 条件、JOIN 条件、ORDER BY、GROUP BY 字段上有合适的索引。
避免过度索引,索引也占用空间和维护成本。
使用覆盖索引 (Extra: Using index)。
注意索引选择性,低选择性字段 (如性别) 建索引效果差。
考虑前缀索引、复合索引的顺序。
改写 SQL:
避免 SELECT *,只选择需要的列。
优化 JOIN:确保关联字段有索引,小表驱动大表。
避免在 WHERE 子句中对字段进行函数操作 (WHERE YEAR(create_time) = 2023 会导致索引失效,改为 WHERE create_time >= '2023-01-01' AND create_time < '2024-01-01')。
分页优化:避免大的 OFFSET,使用基于游标的分页 (WHERE id > last_id LIMIT n)。
合理使用批量操作。
数据库设计 :合理的范式/反范式设计,选择合适的数据类型,避免过度使用大对象 (TEXT/BLOB)。
总结
故障排查 :遵循从基础到深入、从外部到内部的原则。日志 (错误日志, 慢查询日志, SHOW SLAVE STATUS) 是最重要的信息来源。监控系统资源 (CPU, 内存, 磁盘, 网络) 是基础。
主从复制 :SHOW SLAVE STATUS\G 是诊断核心,重点关注 IO/SQL 线程状态和错误信息。延迟问题需综合分析资源、事务大小、并行度。
优化:
硬件是基石,尤其内存和磁盘。
配置调优 需谨慎,以监控为依据,innodb_buffer_pool_size 是关键。
SQL 优化 是常态工作,通过慢日志和 EXPLAIN 定位问题,索引设计和 SQL 改写是主要手段。
预防性监控:建立完善的监控系统 (Prometheus + Grafana, Zabbix 等),持续跟踪性能指标和潜在问题,比故障发生后再排查更重要。