数据库出问题影响最大。这篇文章整理了 MySQL 最常见的几个故障和对应的排查思路,以及两个能直接用的运维脚本。

一、先掌握排查三件套

# 1. 服务状态
sudo systemctl status mysql

# 2. 错误日志(最重要的排障入口)
sudo tail -n 100 /var/log/mysql/error.log

# 3. 能否连上、基础健康状态
mysqladmin -uroot -p status
mysqladmin -uroot -p ping

二、故障 1:MySQL 连不上

排查顺序:

# 服务有没有起
systemctl status mysql
# 端口是否监听(默认 3306)
ss -tlnp | grep 3306
# 能不能本地连
mysql -uroot -p
# 是不是 socket 路径问题(看 my.cnf)
grep socket /etc/mysql/my.cnf

常见原因: 服务没起、端口被防火墙拦、skip-networking 被打开、socket 路径不一致、密码/账号错误。

三、故障 2:too many connections(连接数满)

# 看当前连接数
mysql -uroot -p -e "SHOW STATUS LIKE 'Threads_connected';"
# 临时调大连接数(改 my.cnf 后要重启才永久生效)
mysql -uroot -p -e "SET GLOBAL max_connections = 500;"

# 永久修改:编辑 /etc/mysql/mysql.conf.d/mysqld.cnf
# [mysqld]
# max_connections = 500

四、故障 3:Access denied(权限报错)

# 查看某个用户有哪些权限、允许哪些主机
mysql -uroot -p -e "SHOW GRANTS FOR 'wpuser'@'localhost';"

# 授权示例
mysql -uroot -p -e "GRANT ALL PRIVILEGES ON wpdb.* TO 'wpuser'@'localhost';"
mysql -uroot -p -e "FLUSH PRIVILEGES;"

常见原因: 用户不存在、主机限制不匹配(如只允许 localhost 却从别处连)、密码错误。

五、故障 4:磁盘满 / binlog 占满空间

# 看磁盘
df -h
# 看 binlog 占了多少
du -sh /var/log/mysql/
# 查看 binlog 保留策略
mysql -uroot -p -e "SHOW VARIABLES LIKE 'expire_logs_days';"

# 临时清理到指定位置
mysql -uroot -p -e "PURGE BINARY LOGS BEFORE NOW() - INTERVAL 3 DAY;"

六、慢查询定位

# 开启慢查询日志(改配置文件重启,或临时开启)
mysql -uroot -p -e "SET GLOBAL slow_query_log = ON;"
mysql -uroot -p -e "SHOW VARIABLES LIKE 'slow_query_log%';"

# 分析某条 SQL 是否走索引
EXPLAIN SELECT * FROM posts WHERE post_title='xxx';
# 重点关注 type(全表扫 ALL / 走索引 range/ref)、rows(扫描行数)

七、脚本 1:MySQL 一键健康检查

#!/bin/bash
set -euo pipefail
MYSQL_PWD='你的密码' mysqladmin -uroot status 2>/dev/null || {
    echo "[ERROR] MySQL 未响应:$(date '+%F %T')" >> /var/log/mysql_check.log
}

注意:生产环境不要明文写密码,可用 ~/.my.cnf(权限 600)或环境变量。

八、脚本 2:数据库自动备份

#!/bin/bash
set -euo pipefail

DB="wpdb"                       # 要备份的库
BACKUP_DIR="/backup/mysql"
KEEP=7                          # 保留 7 天
DATE=$(date +%F)

mkdir -p "$BACKUP_DIR"

# 单库备份(用 ~/.my.cnf 提供密码,避免命令行暴露)
mysqldump --single-transaction --quick "$DB" > "$BACKUP_DIR/${DB}-${DATE}.sql"

# 保留最近 KEEP 天的备份,删除更早的
find "$BACKUP_DIR" -name "*.sql" -mtime +"$KEEP" -exec rm -f {} \;

echo "[$(date '+%F %T')] 备份完成:$BACKUP_DIR/${DB}-${DATE}.sql"

配合 crontab:0 3 * * * /root/scripts/backup_mysql.sh

分类: 数据库