MySQL 故障排查与生产环境优化

一、 MySQL 单实例故障排查

当 MySQL 单实例出现问题时,可按以下步骤进行排查:

基础检查

服务状态 :确认 MySQL 服务是否正在运行 (systemctl status mysqlservice mysql status)。

网络连接 :检查端口是否监听 (netstat -tuln | grep 3306),防火墙是否开放端口。

连接尝试 :尝试使用命令行客户端 (mysql -u user -p) 或其他工具连接,记录错误信息。

错误日志首要查看 MySQL 的错误日志文件 (通常位于 /var/log/mysql/error.log/var/log/mysqld.log),其中记录了启动、运行、关闭过程中的详细错误信息。

资源瓶颈检查

CPU :使用 tophtop 查看 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; 查看当前所有连接的状态,寻找阻塞的查询 (StateLocked, Sending data, Sorting result 等耗时操作)。

锁信息 :对于 InnoDB, 使用 SHOW ENGINE INNODB STATUS\G 查看 TRANSACTIONSLATEST 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_RunningNo)。

查看复制状态

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 磁盘。

文件系统 :如 xfsext4 (配置 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 :对慢查询执行 EXPLAINEXPLAIN 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 等),持续跟踪性能指标和潜在问题,比故障发生后再排查更重要。

相关推荐
雪碧聊技术2 小时前
数据库的第一、二、三范式分别解决了什么问题?一文详解
数据库·部分依赖·传递依赖·第一、二、三范式·列的原子性
卢傢蕊3 小时前
MySQL全量、增量备份与恢复
数据库·mysql
码农垦荒笔记3 小时前
MySQL主从延迟根因诊断法:从现象到本质的全链路排查指南
数据库·mysql·主从复制
我不是8神3 小时前
CAP 定理与 etcd 核心知识点总结
数据库·etcd
kiku18183 小时前
Mysql故障排查与优化
数据库·mysql
刘~浪地球4 小时前
Redis 从入门到精通(二):数据类型详解
数据库·redis·缓存
RisunJan4 小时前
Linux命令-mysqlimport(为MySQL服务器用命令行方式导入数据)
linux·服务器·mysql
小韩博4 小时前
代码审计-PHP原生开发篇&SQL注入&数据库监控&正则搜索&文件定位&静态分析
数据库·sql
qq_196976174 小时前
python的sql解析库-sqlparse
数据库·python·sql