📌 环境说明
操作系统:Rocky Linux 9 (RHEL 9 系列)核心痛点:根目录(/)空间爆满,导致大批量数据导入或业务写入时物理空间耗尽。🚨 告警源头
当服务器根分区(/)利用率达到 100% 时,MySQL 会因底层的 InnoDB 存储引擎无法再分配物理页而强行中止写入,并在客户端抛出以下经典报错:此时通过 df -Th 命令会发现,/ 分区可用空间为 0,而 /home 或其他大分区尚有数百吉字节(GB)的闲置空间。此时,将 MySQL 的数据目录(datadir)安全迁移至高容量分区是根本的解决之道。找到占用空间大的目录 最终定位到 /var/lib/mysql这个目录[root@localhost sqldumps]
du -h -x -d 1 /var/lib/mysql | sort -hr | head -n 1068G /var/lib/mysql15G /var/lib/mysql/db_market_prod
🛠️ 第一阶段:数据安全剥离与同步
在迁移过程中,数据完整性是第一要务。必须严格遵循“先停后复制”的原则。1. 彻底停止 MySQL 服务
严禁在运行状态下复制数据文件,否则会导致数据页不一致、损坏。检查服务状态,确保其已处于 inactive (dead) 状态:2. 创建新目录并无损同步数据
假定新迁移的目标大分区路径为 /home/mysql_data。为了确保文件的所属用户(User)、所属组(Group)、权限模式(Mode)以及时间戳完全保持原样,必须使用-a(Archive)参数进行归档复制:mkdir -p /home/mysql_datacp -a /var/lib/mysql/* /home/mysql_data/
3. 校正目录权限
确保新目录及其子文件的拥有者完全变更为 mysql 进程用户,权限策略通常建议调整为 750(属主拥有读写执行,属组拥有读执行,其他人无权限):chown -R mysql:mysql /home/mysql_datachmod 750 /home/mysql_data
📝 第二阶段:重构服务配置文件
MySQL 8.0 在启动时需要同时兼顾服务端(Server)和本地连接客户端(Client)的 Socket 通信,因此需要双向修改。1. 修改服务端配置
打开 Rocky Linux 9 默认的 MySQL 服务端配置文件:vi /etc/my.cnf.d/mysql-server.cnf
在 [mysqld] 模块下,定位并修改以下两个核心参数(若不存在则手动添加):mysqld]datadir=/home/mysql_datasocket=/home/mysql_data/mysql.sock
2. 修改客户端配置
若仅修改服务端,本地执行 mysql -uroot -p 命令时,客户端工具仍会执着于去旧路径寻找通讯套接字,引发 ERROR 2002 报错。vi /etc/my.cnf.d/client.cnf
在 [client] 模块正下方,明确指定新的 Socket 路径:[client]socket=/home/mysql_data/mysql.sock
可以先执行以下命令启动如下命令(如何无法正常启动可以执行第三阶段)systemctl start mysqldsystemctl status mysqld
🛑 第三阶段:攻克系统级安全屏障(核心避坑)
在 Rocky Linux 9 中,现代化的安全沙箱机制极其严密。若直接启动服务,必定遭遇 OS errno 13 - Permission denied(权限拒绝)闪退。必须降伏以下两大系统级“守门神”。1. 解除 Systemd 的家目录保护(ProtectHome)
在 Rocky Linux 9 中,Systemd 默认开启了针对 /home 目录的保护机制,防止公共服务越权读写。我们需要通过创建服务覆盖文件(Override)来关闭它:创建配置覆盖目录mkdir -p /etc/systemd/system/mysqld.service.d# 写入关闭保护规则cat <<EOF > /etc/systemd/system/mysqld.service.d/override.conf[Service]ProtectHome=falseEOF# 强行刷新 Systemd 控制台配置systemctl daemon-reload
2. 修复 SELinux 安全上下文(Context)
SELinux 默认只允许 mysqld_t 进程访问带有 mysqld_db_t 标签的路径。直接将数据移入 /home 会导致标签错乱。严谨做法(非关闭 SELinux,而是为其配置合规标签):1. 向系统注册新路径的安全上下文规则semanage fcontext -a -t mysqld_db_t"/home/mysql_data(/.*)?"# 2. 将规则强行刷新应用到新目录的所有子文件上restorecon -Rv /home/mysql_data
🚀 第四阶段:验证与无痛上线
1. 启动服务
systemctl start mysqldsystemctl status mysqld
看到控制台输出绿色的 Active: active (running),代表底层通信与安全屏障已全线打通。2. 基准验证
mysql -uroot -p -e "SHOW VARIABLES LIKE 'datadir';"
+---------------+-------------------+| Variable_name | Value |+---------------+-------------------+| datadir | /home/mysql_data/ |+---------------+-------------------+
💡 运维补充:企业级最佳实践(Best Practices)
为了使整个技术方案达到生产线级别(Production-Ready)的严谨度,建议在后续清理和优化中追加以下两项最佳实践:1. “冷冻期”安全容灾策略(严禁立刻执行 rm -rf)
当看到新库运行正常后,绝大多数小白会盲目执行rm -rf /var/lib/mysql。这种操作容错率为零,极其危险!将原目录重命名为备份目录,在物理上不占用旧路径,但保留数据底线
mv /var/lib/mysql /var/lib/mysql.bak2026让系统和业务在线运行24 到 48 小时。在此期间密切观察核心业务的读写情况。确认没有任何依赖或硬编码错误后,再于低峰期执行终极清理,彻底释放根目录空间。2. 独立私有临时目录(tmpdir)优化
由于大文件导入或复杂 SQL 的多表 JOIN 会在系统的 /tmp 产生大量临时碎片,如果根目录依然紧张,极易引发二次崩溃。建议在新路径下为 MySQL 剥离出一条独立的临时管道:mkdir -p /home/mysql_data/tmpchown -R mysql:mysql /home/mysql_data/tmpchmod 770 /home/mysql_data/tmp
随后在 /etc/my.cnf.d/mysql-server.cnf 里的 [mysqld] 模块追加一行:tmpdir=/home/mysql_data/tmp
重启服务后,MySQL 所有的内部排序、临时建表动作都将限制在 /home 高容量分区中运行,彻底保障了整个生产环境的抗压与稳健性。