mysql不支持配置多个datadir,仅允许单一datadir路径;所谓“多目录”只能通过停服后对库级目录建软链接实现,但需确保同挂载点、正确权限及selinux/apparmor策略。

MySQL 不支持配置多个 datadir
MySQL 启动时只认一个 datadir,硬编码逻辑决定了它无法像 PostgreSQL 那样用 tablespace 分散到不同路径。所谓“多个数据存放目录”,实际只能靠软链接(symbolic link)在 datadir 内部做局部映射——比如把某个库或某张表的 .ibd 文件链到另一块磁盘,但前提是整个 datadir 本身仍是单一路径。
只能对单个数据库目录做软链接,且必须停服操作
常见错误是试图给 /var/lib/mysql/mydb 单独建软链,而保留 /var/lib/mysql 为原位置。这会导致:
-
SHOW DATABASES漏掉该库,因为 MySQL 扫描datadir子目录时会跳过符号链接(除非是datadir自身) -
DROP DATABASE mydb可能误删新路径下的物理文件,因元数据和文件系统路径错位 - InnoDB 表空间校验失败,报
Tablespace is missing for table
正确做法是:
- 执行
systemctl stop mysql,确认ps aux | grep mysql无残留进程 - 把目标库整个移动过去:
mv /var/lib/mysql/mydb /data/extra/mydb - 在原位置重建软链:
ln -sf /data/extra/mydb /var/lib/mysql/mydb - 确保
/data/extra/mydb属主为mysql:mysql,否则启动时报Can't open the mysql.plugin table
软链接跨文件系统时,InnoDB DDL 会失败
如果 /var/lib/mysql 在 /dev/sda1,而软链指向的 /data/extra/mydb 在 /dev/sdb1,执行 ALTER TABLE t ENGINE=InnoDB 会直接报错:
ERROR 1034 (HY000): Incorrect key file for table 't'; try to repair it
根本原因是 InnoDB 的 .ibd 文件和数据字典(ibdata1 或 mysql.ibd)必须位于同一挂载点。软链只是路径转发,不改变底层 IO 所在设备。遇到这类问题,唯一稳妥解法是把整个 datadir 迁移到新磁盘并用软链挂回原路径,而不是零散拆分。
SELinux 和 AppArmor 是最常被忽略的权限拦路虎
即使 chown -R mysql:mysql /data/extra 做全了,CentOS/RHEL 默认启用 SELinux,Ubuntu 默认启用 AppArmor,它们会拦截 mysqld 对非标准路径的访问。现象是服务卡在启动阶段,日志里反复出现:
Permission denied 或 Operation not supported
临时验证是否是它导致的:运行 setenforce 0(SELinux)或 sudo systemctl stop apparmor(Ubuntu),再试启动。确认后必须打策略:
- SELinux:
semanage fcontext -a -t mysqld_db_t "/data/extra(/.*)?",然后restorecon -Rv /data/extra - AppArmor:编辑
/etc/apparmor.d/usr.sbin.mysqld,在/var/lib/mysql/** rwk,下加一行/data/extra/** rwk,,再执行sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.mysqld
没配好这些,软链永远是“看着行,跑起来崩”。











