1. Ubuntu下MySQL 8数据目录迁移实战指南
上周在给客户部署新系统时遇到一个典型问题:默认安装的MySQL 8数据目录占用了根分区空间,导致磁盘告警。这种场景在数据库应用中非常常见,特别是当/var/lib/mysql所在分区容量不足时。本文将完整记录我在Ubuntu 22.04 LTS上迁移MySQL 8数据目录的全过程,包含你可能遇到的AppArmor权限陷阱和配置细节。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与现状分析
2.1 系统环境确认
首先确认基础环境:
bash复制# 查看系统版本
lsb_release -a
# 检查MySQL版本
mysql --version
我的测试环境是Ubuntu 22.04.3 LTS,MySQL版本为8.0.34-0ubuntu0.22.04.1。注意不同小版本可能会有细微差异。
2.2 磁盘空间检查
使用df -h查看当前磁盘分区情况,典型问题如下:
code复制/dev/nvme0n1p2 50G 45G 2.0G 96% /
/dev/nvme0n1p3 500G 12G 488G 3% /data
可见根分区即将耗尽,而/data分区有充足空间,这正是我们需要迁移数据目录到/data/mysql的原因。
3. 完整迁移步骤详解
3.1 停止MySQL服务
首先安全停止MySQL服务:
bash复制sudo systemctl stop mysql
sudo systemctl status mysql # 确认状态为inactive
重要提示:务必先停止服务,直接移动文件可能导致数据损坏
3.2 迁移数据文件
创建新目录并复制数据:
bash复制sudo mkdir -p /data/mysql
sudo chown -R mysql:mysql /data/mysql
sudo rsync -av /var/lib/mysql/ /data/mysql/
使用rsync比简单cp更可靠,它能保留所有文件属性和权限。完成后建议验证:
bash复制sudo du -sh /var/lib/mysql /data/mysql # 对比大小应基本一致
sudo ls -l /data/mysql # 确认所有者为mysql
3.3 修改MySQL配置
编辑配置文件:
bash复制sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
找到datadir配置项,修改为:
code复制datadir = /data/mysql
同时检查socket路径是否需要同步修改(通常保持默认即可):
code复制socket = /var/run/mysqld/mysqld.sock
3.4 处理AppArmor权限
这是最容易被忽视的关键步骤!Ubuntu的AppArmor会限制MySQL访问非默认路径,需要更新配置:
bash复制sudo nano /etc/apparmor.d/usr.sbin.mysqld
找到以下行并添加新路径:
code复制/var/lib/mysql/ r,
/var/lib/mysql/** rwk,
/data/mysql/ r,
/data/mysql/** rwk,
保存后重新加载AppArmor:
bash复制sudo systemctl reload apparmor
3.5 修改systemd服务单元
为确保服务启动时使用新路径,编辑服务文件:
bash复制sudo systemctl edit mysql
添加以下内容:
code复制[Service]
ProtectHome=false
ReadWritePaths=/data/mysql
3.6 启动并验证服务
逐步执行:
bash复制sudo systemctl start mysql
sudo systemctl status mysql # 检查是否active
mysql -u root -p -e "SHOW VARIABLES LIKE 'datadir';" # 应显示新路径
4. 常见问题解决方案
4.1 启动时报错"Can't create/write to file"
典型错误日志:
code复制[ERROR] [MY-010131] [Server] Can't create/write to file '/data/mysql/ibdata1'
解决方案:
- 确认/data/mysql所有者是mysql用户
- 检查AppArmor配置是否生效
- 查看SELinux状态(Ubuntu默认不启用)
4.2 客户端连接失败
如果遇到连接问题:
- 检查socket路径是否一致
- 确认bind-address配置(通常应为127.0.0.1)
- 防火墙规则:
bash复制sudo ufw allow mysql
4.3 性能优化建议
新目录建议添加mount选项:
code复制/dev/nvme0n1p3 /data ext4 defaults,noatime,nodiratime 0 2
并在my.cnf中添加:
code复制innodb_flush_method = O_DIRECT
innodb_io_capacity = 2000
5. 回滚方案
万一迁移失败,可按以下步骤恢复:
- 停止MySQL服务
- 将原目录重命名备份:
bash复制sudo mv /var/lib/mysql /var/lib/mysql_backup
- 将新目录移回原位置:
bash复制sudo mv /data/mysql /var/lib/mysql
- 恢复原始配置文件和AppArmor设置
- 重启服务
6. 迁移后的维护建议
- 监控新分区空间使用情况:
bash复制watch -n 60 df -h /data
- 调整备份脚本路径:
bash复制# 原备份命令可能类似
mysqldump -u root -p dbname > /backup/db.sql
# 需要确认备份目录是否在新分区
- 定期验证数据完整性:
bash复制mysqlcheck -u root -p --all-databases
经过这次实战,我特别建议在首次部署MySQL时就规划好数据目录位置,避免后期迁移。如果必须迁移,务必做好完整备份并逐步验证每个步骤。
