1. 故障现象初探MySQL服务去哪儿了那天早上刚到公司就接到同事电话说系统重启后MySQL死活起不来。登录服务器第一件事就是检查服务状态结果systemctl status mysql直接给我泼了盆冷水——Unit mysql.service not found。这感觉就像你去开车发现钥匙孔都不见了连拧钥匙的机会都没有。遇到这种情况先别慌我习惯用三板斧排查确认服务名到底是mysql还是mysqld老版本常用mysqld检查/etc/init.d/目录下是否存在服务脚本用ps -ef | grep mysql看看是否有残留进程当时发现/etc/init.d/mysqld这个文件是存在的说明服务脚本没丢。但执行service mysqld start却报Data directory not found这就很有意思了——服务脚本在但找不到数据目录典型的魂在身已远症状。2. 寻踪觅迹定位MySQL的家数据目录丢失这种问题十有八九是配置文件出了问题。先祭出whereis mysql大法在/usr/local/mysql找到了二进制文件。接着检查/etc/my.cnf发现里面配置的datadir竟然是/var/lib/mysql但实际数据存放在/data/mysql——这就像你按导航去公司结果导航把你带到了十年前的老办公楼。这里教大家几个找数据目录的实用技巧检查my.cnf中datadir参数可能有多个配置文件按顺序读取查看ps -ef | grep mysql命令输出中的--datadir参数搜索常见目录find / -name mysql -type d 2/dev/null检查最近修改过的MySQL文件find / -mtime -7 -name *ibd 2/dev/null3. 配置文件捉虫记修正datadir后用mysqld --defaults-file/etc/my.cnf手动启动结果进程卡住不报错也不退出。这种最让人头疼就像程序编译时光标一直闪但不出结果。这时候就得查错误日志了MySQL的错误日志通常位于/var/log/mysqld.log数据目录下的hostname.err通过show variables like log_error;查询当然现在用不了我最后在/data/mysql/mysql-error.log发现了线索——原来之前的安装是用源码编译的但服务管理用的却是系统自带的systemd单元两者路径没对上。这就好比用德国标准零件去修美国车尺寸看着差不多但就是拧不紧。4. 服务管理器的宫斗戏CentOS 7开始用systemd取代了传统的SysV init但MySQL安装时可能两种服务管理方式混着来。我遇到过最奇葩的情况是源码安装时创建了/etc/init.d/mysqld系统升级后自动生成了/usr/lib/systemd/system/mysqld.service两个服务文件配置的参数互相冲突正确的处理姿势应该是# 先停掉所有MySQL相关服务 systemctl stop mysqld service mysqld stop pkill mysqld # 清理残留的service文件 rm -f /etc/init.d/mysqld rm -f /usr/lib/systemd/system/mysqld.service # 重新创建systemd单元文件 cat /etc/systemd/system/mysql.service EOF [Unit] DescriptionMySQL Server Afternetwork.target [Service] Usermysql Groupmysql ExecStart/usr/local/mysql/bin/mysqld --defaults-file/etc/my.cnf Restarton-failure RestartSec5s [Install] WantedBymulti-user.target EOF # 重新加载配置 systemctl daemon-reload5. PID文件引发的血案当终于看到服务启动成功的提示时还没来得及高兴mysql -u root -p又给了当头一棒——Cant connect to local MySQL server through socket /tmp/mysql.sock。检查发现更离谱的事服务实际运行的PID文件和客户端查找的PID文件根本不是同一个这种问题通常有三种可能配置文件被多个位置覆盖/etc/my.cnf、/etc/mysql/conf.d/、~/.my.cnf启动时用--pid-file参数覆盖了配置残留的临时文件导致冲突我的解决步骤是# 找出实际使用的pid文件 ps -ef | grep mysqld | grep -oP pid-file\K[^ ] # 确认客户端查找的pid文件位置 mysql --help | grep -A1 pid-file # 临时解决方案创建符号链接 ln -s /actual/path/mysqld.pid /expected/path/mysqld.pid # 永久解决方案统一配置文件中的配置 sed -i /^pid-file/d /etc/my.cnf echo pid-file/consistent/path/mysqld.pid /etc/my.cnf6. 权限问题的隐身衣你以为这就结束了太天真了重启服务后又遇到Could not create unix socket lock file错误。这是典型的权限问题MySQL服务运行时用的是mysql用户但数据目录可能被root用户创建导致mysql用户没权限写。正确的权限设置应该是chown -R mysql:mysql /data/mysql chmod 750 /data/mysql # 特别要注意tmp目录 chmod 1777 /data/mysql/tmp这里有个坑如果用了AppArmor或SELinux可能还需要额外配置# 检查SELinux状态 sestatus # 如果是enforcing状态需要添加安全上下文 semanage fcontext -a -t mysqld_db_t /data/mysql(/.*)? restorecon -Rv /data/mysql7. 终极武器错误日志分析指南经过上述折腾如果服务还是起不来那就得认真研读错误日志了。MySQL的错误日志通常包含从Fatal到Note多个级别信息我总结了个快速定位技巧先找[ERROR]标记的致命错误检查最后出现的InnoDB相关消息关注starting as process之后的第一个错误注意Could not open file类权限错误查看Server socket created on IP: 0.0.0.0等网络绑定信息举个例子常见的InnoDB恢复问题可以这样处理# 先尝试安全模式启动 mysqld --innodb_force_recovery1 # 如果级别1不行逐步尝试更高等级最大为6 # 成功启动后立即备份数据 mysqldump -A backup.sql # 然后重新初始化数据目录 mv /data/mysql /data/mysql.bak mkdir /data/mysql chown mysql:mysql /data/mysql mysqld --initialize-insecure --usermysql --datadir/data/mysql8. 防患于未然MySQL运维最佳实践踩过这么多坑后我总结了几条血泪经验安装规范化使用官方二进制包而非源码编译除非有特殊需求记录所有安装参数到文档统一配置文件路径和数据目录位置配置管理# 创建配置备份 cp /etc/my.cnf /etc/my.cnf.bak-$(date %F) # 使用include方式组织配置 echo !includedir /etc/mysql/conf.d/ /etc/my.cnf服务管理只用systemd管理服务CentOS 7为MySQL创建专用用户设置合理的OOM调整参数echo vm.overcommit_memory 1 /etc/sysctl.conf sysctl -p备份策略至少保留两份完整备份定期验证备份可恢复性使用物理备份逻辑备份组合最后说个真实案例有次客户坚持要用/home/mysql作为数据目录结果磁盘满了导致服务崩溃。所以切记——MySQL的数据目录一定要放在专用分区最好用LVM管理方便扩展。