前言
生产环境执行 UPDATE 语句时,没有任何预警地飙出一个锁冲突提示。可一查进程,实际锁进程一个都没找到。这时候,df -h 一查,好家伙——磁盘空间直接爆了。MySQL 服务像是被点了xue,卡死、无法连接,整个就是一副“宕机待办”的状态。
既然磁盘满了,第一步反应就是腾空间。二话不说,rm -rf 上场,把服务器上的备份数据和所有 binlog 文件(mysql-bin.000*)全清了一遍。同时注意到一个异常:ibtmp1 文件膨胀到了 993G。这不太对劲,于是用 vim my.cnf 加了一条限制 ibtmp1 大小的配置。
然而,重启服务的尝试却碰了钉子。./mysql.server start 报错,提示有 /var/lock/subsys/mysql 锁文件挡路。删除锁文件后,服务依然启动失败。顺着错误日志往下查,才定位到问题的根子——binlog 索引文件 mysql-bin.index 记录的内容和实际磁盘上已存在的 binlog 文件根本对不上。用 vim 清空索引文件,再配合 chown 修复目录权限,MySQL 终于成功重启。
二、故障处理核心命令(源自实际执行日志)
1. 故障排查类
| 命令用途 | 具体命令 |
|---|---|
| 切换目录定位文件 | cd /data/、cd bigdata/mysql/、cd /data/mysql-5.7.37/data/等系列cd命令 |
| 查看目录 / 文件列表 | ll、ll -h |
| 排查磁盘空间 | df -h(多次执行,确认磁盘占用及释放情况) |
| 查看文件 / 目录大小 | du、du -sh、du -h --max-depth=1、du -ah | sort -hr、du -sh -d 1 |
| 查看 MySQL 进程状态 | ps -ef | grep mysql、ps -ef | grep mysql.server |
| 查看服务运行状态 | ./mysql.server status、systemctl status mysql、systemctl status mysqld |
| 查看端口占用 | netstat -tlnp | grep :3306 |
| 检索历史操作 | history、history | grep status、history | grep mysql |
2. 故障处理类
| 命令用途 | 具体命令 |
|---|---|
| 释放磁盘空间(不规范) | rm -rf mysql-bin.000*(批量删除 binlog 文件) |
| 修改 MySQL 配置文件 | vim my.cnf(添加innodb_temp_data_file_path = ibtmp1:12M:autoextend:max:10G) |
| 管理 MySQL 服务 | ./mysql.server start、./mysql.server stop |
| 删除服务锁文件 | rm -f /var/lock/subsys/mysql |
| 修复文件 / 目录权限 | chown -R mysql:mysql /data/mysql-5.7.37/data、chown -R mysql:mysql /data/mysql-5.7.37 |
| 编辑 binlog 索引文件 | vim mysql-bin.index(清空无效记录) |
3. 辅助操作类
| 命令用途 | 具体命令 |
|---|---|
| 查看命令帮助 | du --help |
| 切换根目录 | cd //、cd /var/lock/subsys/等 |
三、核心问题原因分析
1. 初始“锁提示”的本质
看上去像是一个数据库锁冲突,但实际是磁盘空间被 ibtmp1(993G)和堆积如山的 binlog 给撑爆了。MySQL 进程因此“假死”,才触发了那条不存在的锁提示。这也是为什么 ps -ef|grep mysql 怎么也找不到锁进程的原因。
2. 磁盘空间耗尽的核心诱因
- 主因:
ibtmp1文件压根没设大小限制,大查询生成的临时表不断往里写,它就这么一路无节制地膨胀到了 993G。 - 次因:binlog 文件也没配置自动清理规则,日积月累,慢慢把磁盘啃光了。
3. MySQL 重启失败的双重原因
- 锁文件残留:MySQL 服务异常退出时,
/var/lock/subsys/mysql这个锁文件没有被自动删除,导致重启直接被挡在门外。 - binlog 索引与文件不一致:批量删除
mysql-bin.000*之后,mysql-bin.index索引文件里那些已被删除的记录却还躺在那里。MySQL 启动时一校验,发现 binlog 完整性对不上,自然就初始化失败了。
4. 权限相关辅助问题
还有一点容易被忽略:部分数据文件的权限不是 mysql 用户的,服务启动时无法正常读写,必须用 chown -R 来修复。
四、本次操作的潜在风险
1. 批量删除 binlog 文件的严重风险
- 数据恢复失效:binlog 是事务日志,全删了就等于把历史数据恢复的路彻底堵死了。
- 主从同步中断:如果存在主从架构,从库找不到这些缺失的 binlog,主从数据就会出问题,同步链路直接断掉。
- 索引文件紊乱:没有通过官方命令删除,直接破坏了
mysql-bin.index和实际 binlog 文件的对应关系,最终引发了启动失败(本次就撞上了这个坑)。
2. 盲目删除锁文件的风险
- 数据损坏:如果 MySQL 进程只是假死还没完全退出,强行删除锁文件后重启,很容易导致数据文件读写冲突,引发表损坏或者数据一致性问题。
- 服务异常叠加:没有搞清楚锁文件产生的根源(比如是不是进程残留导致的),仅仅删除文件,重启后很可能又会重新生成锁文件。
3. 批量修改权限的风险
- 权限过度开放/错误:
chown -R mysql:mysql把整个安装目录的权限都改了,如果目录里混着非 MySQL 的文件,对其他程序来说就是个困扰。 - 安全隐患:权限配置不当(比如过度开放),容易成为被攻击的目标。
4. 配置修改未验证的风险
- 启动失败加剧:修改
my.cnf后,没有用mysqld --help --verbose验证一下参数合法性。万一格式写错了,服务启动就会直接挂掉,排查成本瞬间翻倍。
五、预防措施(避免问题再次发生)
1. 规范 binlog 管理(核心避坑)
- 配置自动清理:在
my.cnf中添加expire_logs_days=3(5.7 版本),自动删除 3 天前的 binlog,避免越堆越多。 - 禁止批量删除:需要删 binlog 时,务必用官方命令
PURGE BINARY LOGS BEFORE 'YYYY-MM-DD HH:MM:SS',它会自动同步更新mysql-bin.index。 - 主从架构特殊处理:删除前先通过
SHOW SLA VE STATUS确认从库已经同步到目标 binlog 位点,别把同步链路给打断了。
2. 限制临时表空间膨胀
- 提前配置兜底:在
my.cnf中固定innodb_temp_data_file_path = ibtmp1:12M:autoextend:max:10G,给ibtmp1划好一条红线。 - 优化查询减少临时表:定期查看慢查询日志,定位那些生成大临时表的查询,然后通过加索引或优化 SQL 来减少对临时表空间的写入。
3. 完善磁盘与服务监控
- 监控项配置:用 Zabbix/Prometheus 等工具监控磁盘使用率(阈值 80% 告警)、
ibtmp1大小(阈值 8G 告警)、binlog 占用空间、MySQL 服务状态及端口连通性。 - 告警响应机制:配置信息/邮件告警,磁盘使用率达到 70% 时就触发预警,别等到完全耗尽才动手。
4. 规范故障处理流程
- 重启前必查三项:①用
ps -ef|grep mysqld确认进程已完全退出;②仔细查看错误日志,定位核心问题;③清理锁文件前,先验证进程状态。 - 配置修改流程:改完
my.cnf,先执行./bin/mysqld --help --verbose | grep 配置项验证合法性,再挑业务低峰期重启服务。 - 权限操作规范:避免递归修改整个目录权限,只对数据目录(
data/)、日志目录等必要的路径做调整。权限设置为755(目录)、660(文件)比较稳妥。
5. 定期巡检与备份
- 每周巡检:①检查
mysql-bin.index与实际 binlog 文件的一致性(diff <(cat mysql-bin.index) <(ls -1 mysql-bin.*));②查看ibtmp1大小及慢查询日志。 - 数据备份:配置全量备份 + binlog 增量备份,这样就算误删了 binlog 或者数据损坏,也不至于血本无归。
六、关键总结
- 本次故障的核心是“不规范操作 + 无配置兜底”:批量删除 binlog 破坏了索引一致性,没有限制
ibtmp1大小直接导致磁盘耗尽,这才是引发连锁问题的真正根源。 - 实际执行的
du、df -h这些排查命令本身没问题,但删除操作(rm -rf mysql-bin.000*)的风险太大了,必须替换成官方规范命令。 - 预防的核心就是“提前配置 + 规范操作”:通过配置自动清理、资源限制规则来减少故障诱因,通过规范命令操作来避免二次故障,最后再辅以监控和备份,形成一个完整的防护体系。

