Errcode: 13错误80%以上由SELinux导致,需先用getenforce确认Enforcing模式,再用sestatus查看策略类型,最后执行setenforce 0验证;若MySQL随即启动成功,即可确定是SELinux上下文不匹配所致。

Errcode: 13 不是权限没给够,而是 SELinux 拦住了——80% 以上的情况,chmod 和 chown 都白改。
怎么快速确认是 SELinux 在拦截?
别急着删日志、改配置、重装 MySQL。先跑三行命令:
-
getenforce:输出Enforcing就基本坐实了 -
sestatus:看Current mode:和Policy MLS status:,确认策略类型(通常是targeted) -
sudo setenforce 0后立刻systemctl start mysqld:如果秒启成功,就是它
注意:setenforce 0 是临时切到 permissive 模式,只记录不拦截,不重启不失效,适合验证。
为什么 /var/lib/mysql 属主属组全对还报错?
因为 SELinux 不看 ls -l,它看的是安全上下文(security context)。即使目录属于 mysql:mysql,只要它的类型不是 mysqld_db_t,mysqld 进程照样被拒绝写入。
- 查当前上下文:
ls -Z /var/lib/mysql,正常应显示类似system_u:object_r:mysqld_db_t:s0 - 如果显示
default_t、var_t或unconfined_u:object_r:...:s0,说明上下文没标对 - 临时修复(重启后失效):
sudo chcon -R -t mysqld_db_t /var/lib/mysql - 永久修复(必须做):
sudo semanage fcontext -a -t mysqld_db_t "/var/lib/mysql(/.*)?",再sudo restorecon -Rv /var/lib/mysql
自定义数据目录(比如 /hc/mysql)或 Docker 挂载失败怎么办?
SELinux 不认路径名,只认标签。你挂 -v /hc/mysql:/var/lib/mysql,宿主机目录的上下文(比如 default_t)会透传进容器,而 mysqld 进程在容器里仍要求 mysqld_db_t,于是静默拒绝。
- 宿主机上先打标签:
sudo semanage fcontext -a -t mysqld_db_t "/hc/mysql(/.*)?"→sudo restorecon -Rv /hc/mysql - Docker 启动时加
:z标签:docker run -v /hc/mysql:/var/lib/mysql:z ...,让 Docker 自动重标上下文 - 漏掉临时路径也会失败:比如
/tmp/ib*文件、自定义pid-file路径,都得单独加规则:sudo semanage fcontext -a -t mysqld_tmp_t "/tmp/ib.*"
哪些布尔值可能影响 MySQL 行为?
有些功能默认被 SELinux 策略禁止,需手动开启:
-
mysqld_can_network:允许网络连接(远程访问必需) -
mysqld_connect_any:允许连接任意端口(如用SELECT ... INTO OUTFILE写网络路径) -
mysqld_disable_trans:允许mysqld在受限范围内切换上下文(导出/导入大文件常用) - 查当前状态:
getsebool -a | grep mysqld;启用并持久化:sudo setsebool -P mysqld_can_network on
真正麻烦的不是“要不要关 SELinux”,而是漏标一个路径、少开一个布尔值,MySQL 就卡在某个环节不动,错误日志里还不提 SELinux —— 得去 /var/log/audit/audit.log 里用 ausearch -m avc -ts recent | grep mysqld 才能抓到真实拦截点。


















