说实话,在 MySQL 安装过程中遭遇权限问题,几乎是每个通过源码或二进制包部署的人都会遇到的典型困境。翻了半天日志,满屏的 Permission denied,那种无力的挫败感确实令人头疼。但归根结底,核心问题往往集中在几个关键点上,只要理清思路就能快速定位并解决。今天就把排查思路和修复方案一次性讲透。
先给出结论:目录 /var/lib/mysql 的归属必须设置为 mysql:mysql,权限为 750;初始化操作必须使用 sudo -u mysql 执行;如果已经用 root 用户初始化了,那就必须清空目录重新来过;同时还要留意 systemd 沙箱、配置文件以及 socket 目录的权限设置。

检查 /var/lib/mysql 目录归属和权限
启动失败时,如果日志里出现 Permission denied 且路径指向 /var/lib/mysql,那么十有八九就是这个问题。直接运行 ls -ld /var/lib/mysql 查看一下,输出格式应该是类似 drwxr-x--- 11 mysql mysql —— 注意第三、四字段都必须显示为 mysql。
如果不对,立即执行以下命令:
sudo chown -R mysql:mysql /var/lib/mysql
sudo chmod 750 /var/lib/mysql
这里有几个细节需要特别留意:
- 千万不要手误写成 chmod 777,MySQL 启动时如果检测到权限过宽,会直接拒绝启动。
- 如果目录本身就不存在,那么先执行 sudo mkdir -p /var/lib/mysql 创建目录并赋予权限,否则 mysqld --initialize 会直接退出。
- chown -R 中的 -R 参数绝对不能省略,否则子目录和文件仍然归 root 用户管理。
确保 mysqld --initialize 以 mysql 用户执行
mysql_install_db 在 MySQL 5.7.6 及以上版本中已经废弃,但很多旧文档仍在沿用。如果你用 root 用户执行 mysqld --initialize,那么 ibdata1、auto.cnf 等文件的属主都会变成 root,后续 mysql 用户根本无法读取。
正确的操作方式如下:
sudo -u mysql mysqld --initialize --datadir=/var/lib/mysql --user=mysql
这里面有两个坑必须避开:
- 一是漏掉 --user=mysql 参数,二是 --datadir 路径写错,这两种情况都会导致初始化生成的文件权限失控。
- 如果已经用 root 初始化过了,那就老老实实清空 /var/lib/mysql 再重新执行。仅靠 chown 去修改单个文件是不够的 —— 比如 ib_logfile* 这类文件的权限可能依然被锁死。
排查 systemd 沙箱限制(ProtectHome / NoNewPrivileges)
如果 journal 日志里只报 Operation not permitted,但 ls -l 查看文件权限却一切正常,这种情况大概率是 systemd 沙箱在作祟。运行 sudo systemctl cat mysqld,重点检查是否存在 ProtectHome=yes 或 NoNewPrivileges=yes。
ProtectHome=yes 会拦截对 /var/lib/mysql 的访问(因为该路径恰好在 ProtectHome 的管控范围内),而 NoNewPrivileges=yes 则会禁止动态加载插件的能力。
如果只是临时调试,可以这样操作:
sudo systemctl edit mysqld,填入以下内容:
[Service] ProtectHome=false NoNewPrivileges=false
在生产环境中,应该通过 SELinux 策略来精确控制,而不是直接关闭保护机制。
确认配置文件和 socket/log 路径权限
MySQL 启动时,如果发现 /etc/my.cnf 的权限是 0666 或者属主不是 root,会直接报 File protection error 并退出。修复方法也很简单:
sudo chown root:root /etc/my.cnf && sudo chmod 644 /etc/my.cnf
systemd 服务默认以 User=mysql 运行,但它不会自动创建父目录。下面这几个路径需要手动创建并授权:
- /run/mysqld(socket 目录)
- /var/log/mysql(日志目录)
- /var/run/mysqld
逐个执行:
sudo mkdir -p /run/mysqld
sudo chown mysql:mysql /run/mysqld
sudo chmod 755 /run/mysqld
需要提醒的是,/run 目录是内存文件系统,重启后内容会清空。如果想长期生效,需要通过 tmpfiles.d 配置来持久化。
在整个排查过程中,最容易被忽略的一个原则是:所有权限修复操作必须在初始化之前完成。一旦用错用户初始化过,仅修改目录权限是没有用的,必须清空后重新执行。另外,setcap 授权只对 /usr/bin/mysqld 这类 ELF 二进制文件有效,对 mysqld_safe 这种 shell wrapper 是没有效果的。
