本文旨在帮助运维和DBA工程师在CentOS操作系统下,对MySQL数据库进行系统化、全面的故障排查。文章涵盖MySQL核心架构原理、常见故障类型、日志分析、性能监控、参数优化、脚本实用示例等,以确保在生产环境中能够快速定位和解决问题。
前言
MySQL在CentOS上的部署架构
故障分类与优先级
日志分析与常用工具
资源层面故障排查
MySQL层面故障排查
性能优化与参数调优
监控与告警实践
案例解析
总结与建议
附录:常用脚本汇总
在高可用、海量数据的生产环境中,MySQL作为常见的关系型数据库,承担着核心业务读写请求。然而,因应用访问压力、配置不当或操作失误等原因,MySQL常出现服务中断、性能瓶颈等故障。CentOS作为Linux发行版的主流服务器操作系统,对MySQL的安装与维护具有广泛应用价值。深入理解MySQL在CentOS上的运行原理及排查方法,对于保障业务稳定至关重要。
本文基于MySQL 5.7/8.0与CentOS 7/8环境,结合实战经验,提供系统化、流程化的故障排查指南,并附带实用脚本与原理解读,帮助读者快速定位并解决各类故障。全文约6000字,涵盖从环境准备到案例分析的全流程。
# 查看OS版本
cat /etc/centos-release
# 查看内核版本
tuname -r
# 查看MySQL版本
mysql -V
MySQL主要存储引擎:InnoDB 与 MyISAM。
InnoDB的关键机制:
innodb_buffer_pool_size
设置原则为可用内存的70%-80%。innodb_log_file_size
限制。undo
表空间。路径 | 说明 |
---|---|
/var/lib/mysql | 默认数据目录 |
/etc/my.cnf | 主配置文件 |
/var/log/mysqld.log | 错误日志 |
/var/log/mysql/mysql.log | 通用查询日志 (若开启) |
/var/log/mysql/mysql-slow.log | 慢查询日志 (若开启) |
/var/run/mysqld | 存放PID文件 |
实际排查时,需结合业务SLA与服务级别协议,优先处理P0/P1故障,确保服务恢复。
错误日志记录MySQL启动、关闭、运行时的异常和警告信息。
# 查看最新日志
tail -n 100 /var/log/mysqld.log
# 持续监控日志变化
tail -f /var/log/mysqld.log
常见错误:
InnoDB: Error: log file ./ib_logfile0 is of different size
:重做日志大小变化,需按步骤安全重建。Can't lock method\
pfs_memory_table_init`: 权限或SELinux导致启动失败。# my.cnf
[mysqld]
general_log=1
general_log_file=/var/log/mysql/mysql.log
实时记录所有SQL请求,便于审计与排查频繁连接。
[mysqld]
slow_query_log=ON
slow_query_log_file=/var/log/mysql/mysql-slow.log
long_query_time=1 # 单位秒
log_queries_not_using_indexes=1
使用pt-query-digest
分辨最耗时的SQL语句:
pt-query-digest /var/log/mysql/mysql-slow.log > slow_report.txt
# 查看MySQL单元日志
ojournalctl -u mysqld -n 200
# 查看当前连接数
mysql> SHOW GLOBAL STATUS LIKE 'Threads_connected';
# 查看InnoDB状态
mysql> SHOW ENGINE INNODB STATUS\G;
# 检查表状态
mysql> CHECK TABLE db_name.table_name;
采用top
, htop
, vmstat
监控CPU与内存使用:
vmstat 2 10
重点关注:
wa
比例(I/O等待)si
/so
(Swap进出)若内存飙高导致Swap,建议调大innodb_buffer_pool_size
或减少查询并增加物理内存。
通过iostat -xz 2 5
查看磁盘I/O:
# 安装sysstat
yum install sysstat -y
iostat -xz 2 5
关注:
%util
接近100%await
与 svctm
若I/O瓶颈,可考虑:
innodb_flush_neighbors=0
利用ping
, netstat
, ss
检测网络状况:
ping database_host -c 10
ss -tnp | grep mysqld
若出现大量TIME_WAIT
或网络丢包,需检查网络链路及 MTU 设置。
配置文件错误
/etc/my.cnf
以及 /etc/my.cnf.d/
下所有包含 .cnf
的文件,确保没有语法错误。mysqld --help --verbose | grep -A1 "Default options"
权限与 SELinux
确保 MySQL 数据目录(默认 /var/lib/mysql
)归属 mysql:mysql
并拥有 700 权限:
chown -R mysql:mysql /var/lib/mysql
chmod -R 700 /var/lib/mysql
如果启用了 SELinux,需要设置正确的安全上下文:
restorecon -R /var/lib/mysql
sestatus # 查看当前 SELinux 模式
临时关闭 SELinux 进行验证:
setenforce 0
systemctl restart mysqld
端口冲突
默认监听 3306,使用 ss
或 netstat
查看是否被其他服务占用:
ss -tnlp | grep 3306
如被占用,可修改 my.cnf
中的 port
参数或停止冲突服务。
InnoDB 重做日志文件大小变化
修改了 innodb_log_file_size
后,必须在关机状态下删除老的 ib_logfile0
/ib_logfile1
,否则因大小不一致启动失败:
systemctl stop mysqld
mv /var/lib/mysql/ib_logfile0 /var/lib/mysql/ib_logfile0.bak
mv /var/lib/mysql/ib_logfile1 /var/lib/mysql/ib_logfile1.bak
systemctl start mysqld
主机绑定与防火墙
在 my.cnf
中检查 bind-address
,确保监听在正确的网卡或 0.0.0.0
。
放通防火墙端口:
firewall-cmd --permanent --add-port=3306/tcp
firewall-cmd --reload
用户授权
查看当前用户及主机范围:
SELECT host, user FROM mysql.user;
扩展授权到任意主机(慎用)或指定网段:
GRANT ALL ON db.* TO 'user'@'%' IDENTIFIED BY 'password';
FLUSH PRIVILEGES;
连接数限制
查看最大连接数及当前使用峰值:
SHOW VARIABLES LIKE 'max_connections';
SHOW GLOBAL STATUS LIKE 'Max_used_connections';
如峰值接近上限,可适当提升 max_connections
,但需关注内存消耗。
超时参数
过短的 wait_timeout
、interactive_timeout
或 connect_timeout
会导致连接断开:
SHOW VARIABLES LIKE '%timeout%';
SET GLOBAL wait_timeout=300;
SET GLOBAL connect_timeout=10;
检测死锁
在 InnoDB 状态输出中查找最新死锁信息:
SHOW ENGINE INNODB STATUS\G;
“LATEST DETECTED DEADLOCK” 段落会展示涉及的事务、SQL 语句及等待资源。
锁等待监控
在 performance_schema
中查看当前等待锁:
SELECT EVENT_ID, THREAD_ID, OBJECT_SCHEMA, OBJECT_NAME, LOCK_TYPE, LOCK_MODE
FROM performance_schema.data_locks
WHERE LOCK_STATUS = 'GRANTED' OR LOCK_STATUS = 'PENDING';
优化建议
慢查询日志分析
通过 pt-query-digest
生成报告,找出最耗时、最频繁执行的 SQL:
pt-query-digest /var/log/mysql/mysql-slow.log > slow_report.txt
执行计划检查
对热点 SQL 使用 EXPLAIN
,确认索引命中率及扫描量:
EXPLAIN SELECT * FROM orders WHERE user_id = 123;
常见索引失效场景
DATE(col)
)会导致全表扫描。varchar
与 int
比较)失去索引。LIKE '%keyword'
)无法使用 B-tree 索引。参数微调
innodb_buffer_pool_size
、tmp_table_size
、join_buffer_size
等内存相关参数,确保大事务与排序操作能在内存中完成,减少磁盘临时表生成。主库状态检查
SHOW MASTER STATUS;
从库状态检查
SHOW SLAVE STATUS\G;
Seconds_Behind_Master
、Last_SQL_Error
、Last_IO_Error
。常见错误及处理
Error 1236 (“Could not find first log file”): 通常因主库 binlog 已清理,从库位置指向已删除日志。需在从库上执行 CHANGE MASTER TO MASTER_LOG_FILE='当前存在的日志', MASTER_LOG_POS=xxx;
并重启复制。
Duplicate entry: 因数据不一致造成,若确认可跳过错误,执行:
STOP SLAVE;
SET GLOBAL sql_slave_skip_counter=1;
START SLAVE;
主从恢复
master_log_file
、master_log_pos
继续增量。InnoDB 自动恢复
InnoDB: Starting crash recovery...
记录。手动恢复历史操作
如果需要回放指定时间段的操作,可使用 mysqlbinlog
从 binlog 重放:
mysqlbinlog --start-datetime="2025-05-01 00:00:00" /var/lib/mysql/mysql-bin.00000* \
| mysql -uroot -p
建议设置为物理内存的 70%–80%,存储热点数据与索引,减少磁盘 I/O。
可动态扩容(MySQL 5.7+):
SET GLOBAL innodb_buffer_pool_size = 8 * 1024 * 1024 * 1024; -- 8GB
innodb_log_file_size × innodb_log_files_in_group
)建议为 buffer pool 的 25%。Max_used_connections
,保持留有余量。max_connections
会带来更多线程内存开销,需权衡。query_cache_size
与 query_cache_limit
。Created_tmp_disk_tables
与 Created_tmp_tables
对比监控临时表使用类型。安装 mysqld_exporter
yum install prometheus-mysqld-exporter -y
systemctl enable --now prometheus-mysqld-exporter
Prometheus 配置
- job_name: "mysql"
static_configs:
- targets: ["db1.example.com:9104", "db2.example.com:9104"]
metrics_path: /metrics
Grafana 仪表盘
指标 | 阈值 | 说明 |
---|---|---|
Threads_connected | > 80% max_conn | 连接数接近极限时告警 |
Innodb_buffer_pool_usage | > 90% | Buffer Pool 使用过高 |
Innodb_row_lock_waits/s | > 50/s | 高频锁等待需优化 SQL |
Replication Lag (秒) | > 1s | 主从延迟超 1s |
Created_tmp_disk_tables/s | > 5/s | 太多磁盘临时表 |
#!/bin/bash
# 检查 replication lag
LAG=$(mysql -uroot -p'pwd' -e "SHOW SLAVE STATUS\G" | awk '/Seconds_Behind_Master/ {print $2}')
if [ "$LAG" -gt 5 ]; then
echo "Replication lag is ${LAG}s" | mail -s "MySQL Replication Alert" [email protected]
fi
ERROR 1037 (HY000): Sort aborted
、No space left on device
df -h
显示 /var/lib/mysql
分区使用率 100%。logrotate
管理 MySQL 日志,并设置磁盘使用告警。Threads_running
常驻高位。现象:Seconds_Behind_Master
持续 >10s,业务读从库时数据不及时。
排查:网络抖动、从库 IO/SQL 线程阻塞、主库写入压力过大。
处理:
slave_net_timeout
;结果:延迟稳定 <1s,读从体验良好。
结构化排查流程
完善日志与监控
定期故障演练
持续性能优化
# 导出 InnoDB 状态
mysql -uroot -p -e "SHOW ENGINE INNODB STATUS\G" > /opt/innodb_status.txt
# 批量检查所有表
for db in $(mysql -uroot -p -e "SHOW DATABASES;" | tail -n +2); do
for tbl in $(mysql -uroot -p -e "SHOW TABLES IN $db;" | tail -n +2); do
mysql -uroot -p -e "CHECK TABLE $db.$tbl FAST" >> /opt/table_check.log
done
done
# 磁盘使用告警
#!/bin/bash
USAGE=$(df /var/lib/mysql | awk 'NR==2{print $5}' | sed 's/%//')
if [ "$USAGE" -gt 80 ]; then
echo "MySQL disk usage at ${USAGE}%." | mail -s "Disk Usage Alert" [email protected]
fi