1. 问题现象与初步排查
那天凌晨2点15分,我的手机突然开始疯狂震动。打开监控系统一看,生产环境的MySQL服务器CPU使用率已经飙到了98%,而且持续了将近20分钟。更诡异的是,这台16核的机器上,有将近80%的CPU消耗都来自一个叫setroubleshootd的进程。
第一反应是检查MySQL的慢查询日志:
bash复制# 查看最近1小时的慢查询
mysqldumpslow -s t -t 10 /var/log/mysql/mysql-slow.log
结果出乎意料——没有发现任何异常慢查询。接着检查了SHOW PROCESSLIST,也没有发现阻塞或异常会话。
这时候我注意到系统日志里有大量这样的记录:
code复制Aug 12 02:10:12 db01 setroubleshoot: SELinux is preventing /usr/sbin/mysqld from write access on the file /var/lib/mysql/ibdata1.
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. SELinux与MySQL的权限冲突
2.1 SELinux安全上下文检查
使用ls -Z检查MySQL数据目录的安全上下文:
bash复制ls -Z /var/lib/mysql
发现部分文件(特别是ibdata1和某些表空间文件)的上下文类型是default_t,而正常应该是mysqld_db_t。
2.2 setroubleshootd的工作原理
这个服务是SELinux的故障诊断工具,当有权限拒绝时:
- 内核通过AVC(Access Vector Cache)记录拒绝事件
- setroubleshootd收集这些日志并尝试生成人类可读的诊断信息
- 如果拒绝事件持续发生,该进程会陷入高CPU循环
通过audit2why查看详细原因:
bash复制grep avc /var/log/audit/audit.log | audit2why
输出显示MySQL进程确实被SELinux阻止了关键文件访问。
3. 问题复现与验证
3.1 临时解决方案测试
首先将SELinux切换到permissive模式验证:
bash复制setenforce 0
CPU立即恢复正常,确认是SELinux引起的问题。
3.2 永久解决方案实施
正确的做法不是禁用SELinux,而是修复安全上下文:
bash复制# 恢复MySQL文件的默认安全上下文
semanage fcontext -a -t mysqld_db_t "/var/lib/mysql(/.*)?"
restorecon -Rv /var/lib/mysql
# 确保SELinux策略允许MySQL操作
setsebool -P mysqld_connect_any on
setsebool -P mysqld_use_nfs on # 如果使用NFS
4. 深度分析与预防措施
4.1 为什么会出现上下文错误
根本原因是之前有人手动恢复了数据库文件:
- 直接cp命令复制了备份文件
- 没有使用
--preserve=context参数 - 或者从不同SELinux策略的服务器迁移数据
4.2 监控SELinux拒绝事件的正确姿势
建议部署这些监控手段:
bash复制# 实时监控AVC拒绝
auditctl -w /var/lib/mysql -p wa -k mysql_avc
# 每日报告生成
sealert -a /var/log/audit/audit.log > /var/log/selinux_report.log
4.3 MySQL在SELinux下的最佳实践
- 备份恢复时使用:
bash复制cp --preserve=context source_file target_location
- 或者用rsync保留上下文:
bash复制rsync -aX source/ destination/
- 定期检查上下文一致性:
bash复制matchpathcon -V /var/lib/mysql/*
那天早上6点,当我把修复方案部署到所有MySQL服务器后,setroubleshootd的CPU占用终于归零。这个案例教会我:在Linux系统上,性能问题往往不是表面看起来那么简单,特别是当安全机制和应用程序产生冲突时,需要像侦探一样层层深入。现在我的监控系统里专门加上了SELinux拒绝事件的报警项,毕竟预防胜于治疗。
