1. Ubuntu下MySQL 8数据目录迁移全攻略
作为Linux系统管理员,最常遇到的挑战之一就是数据库存储空间不足的问题。上周我的生产服务器就遇到了根分区即将爆满的警报,而罪魁祸首正是MySQL那不断膨胀的数据文件。通过将数据目录迁移到大容量挂载点,不仅解决了当前危机,还让后续维护更加灵活。下面分享我在Ubuntu 22.04 LTS上迁移MySQL 8数据目录的完整过程,包括那些官方文档没写的实战细节。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 环境准备与风险控制
2.1 系统环境确认
首先通过以下命令确认基础环境:
bash复制# 查看系统版本
lsb_release -a
# 检查MySQL版本
mysql --version
# 确认当前数据目录
sudo mysql -e "SHOW VARIABLES LIKE 'datadir';"
典型输出显示:
code复制Distributor ID: Ubuntu
Description: Ubuntu 22.04.3 LTS
mysql Ver 8.0.35-0ubuntu0.22.04.1 for Linux on x86_64 ((Ubuntu))
datadir /var/lib/mysql/
重要提示:操作前务必对数据库进行完整备份,推荐使用mysqldump和物理文件双备份:
bash复制# 逻辑备份
mysqldump -u root -p --all-databases > full_backup.sql
# 物理备份
sudo systemctl stop mysql
sudo cp -rp /var/lib/mysql /var/lib/mysql_backup
sudo systemctl start mysql
2.2 新存储规划
选择新数据目录位置时需要考虑:
- 分区剩余空间至少是当前数据大小的3倍
- 推荐使用XFS或EXT4文件系统
- 避免使用网络存储(NFS等)以防性能问题
我选择挂载在/data/mysql目录,先确认磁盘空间:
bash复制df -h /data
输出应显示足够容量,如:
code复制Filesystem Size Used Avail Use% Mounted on
/dev/nvme1n1 500G 25G 475G 5% /data
3. MySQL数据目录迁移实操
3.1 配置文件调整
修改MySQL配置文件前,先做版本适配检查:
bash复制# 确认使用的配置文件路径
sudo mysql --help | grep "Default options"
Ubuntu 22.04默认使用/etc/mysql/mysql.conf.d/mysqld.cnf,添加以下配置:
ini复制[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
[client]
socket=/data/mysql/mysql.sock
关键细节:Ubuntu的AppArmor安全模块会限制MySQL访问非默认路径,必须同步修改安全策略:
bash复制sudo vim /etc/apparmor.d/usr.sbin.mysqld
找到以下行并添加新路径:
code复制/var/lib/mysql/ r,
/var/lib/mysql/** rwk,
/data/mysql/ r,
/data/mysql/** rwk,
重载配置:
bash复制sudo systemctl restart apparmor
3.2 数据迁移过程
分步骤执行迁移:
bash复制# 停止MySQL服务
sudo systemctl stop mysql
# 复制数据文件(保留权限)
sudo rsync -av /var/lib/mysql/ /data/mysql/
# 修改所有权
sudo chown -R mysql:mysql /data/mysql
# 检查文件完整性
sudo mysqlcheck --all-databases --check-upgrade -u root -p
3.3 服务重启与验证
处理常见的启动问题:
bash复制# 尝试启动服务
sudo systemctl start mysql
# 如果失败,查看日志
sudo tail -n 50 /var/log/mysql/error.log
常见错误及解决方案:
-
Socket文件路径问题:
bash复制sudo mkdir /var/run/mysqld sudo chown mysql:mysql /var/run/mysqld -
权限不足错误:
bash复制sudo semanage fcontext -a -t mysqld_db_t "/data/mysql(/.*)?" sudo restorecon -Rv /data/mysql
成功启动后验证:
bash复制# 确认新数据目录生效
mysql -e "SHOW VARIABLES LIKE 'datadir';"
# 测试数据库操作
mysql -e "CREATE DATABASE migration_test; DROP DATABASE migration_test;"
4. 深度问题排查指南
4.1 AppArmor拦截分析
当遇到权限拒绝但文件权限正确时,使用以下命令检查AppArmor日志:
bash复制sudo cat /var/log/syslog | grep apparmor
典型错误示例:
code复制apparmor="DENIED" operation="open" profile="/usr/sbin/mysqld"
name="/data/mysql/ibdata1" pid=1234 comm="mysqld" requested_mask="r"
denied_mask="r" fsuid=111 ouid=111
解决方案:
bash复制# 临时设置为宽容模式
sudo aa-complain /usr/sbin/mysqld
# 永久解决方案是更新AppArmor配置如前文所述
4.2 SELinux环境处理
在启用SELinux的系统(如Rocky Linux)上还需:
bash复制sudo semanage fcontext -a -t mysqld_db_t "/data/mysql(/.*)?"
sudo restorecon -Rv /data/mysql
4.3 残留文件清理
迁移成功后,建议保留原数据目录7天后,执行:
bash复制sudo mv /var/lib/mysql /var/lib/mysql_old
sudo mkdir /var/lib/mysql # 避免某些安装包报错
5. 性能优化建议
新的数据目录配置建议:
-
挂载参数优化:
bash复制# /etc/fstab 示例 UUID=xxxx-xxxx /data ext4 defaults,noatime,nodiratime,barrier=0 0 2 -
MySQL配置调整:
ini复制innodb_flush_method = O_DIRECT innodb_io_capacity = 2000 innodb_io_capacity_max = 4000 -
内核参数优化:
bash复制# /etc/sysctl.conf vm.swappiness = 1 vm.dirty_ratio = 10 vm.dirty_background_ratio = 5
6. 自动化维护脚本
创建定期维护脚本/usr/local/bin/mysql_maintenance.sh:
bash复制#!/bin/bash
# 自动清理旧备份
find /data/mysql_backups -name "*.sql.gz" -mtime +30 -delete
# 优化表
mysql -e "SET GLOBAL innodb_fast_shutdown=0;"
mysqlcheck -o --all-databases -u root -p
# 刷新日志
mysqladmin flush-logs
设置定时任务:
bash复制sudo chmod +x /usr/local/bin/mysql_maintenance.sh
sudo crontab -e
# 添加:
0 3 * * 6 /usr/local/bin/mysql_maintenance.sh
7. 回滚方案设计
当迁移出现严重问题时,按步骤回滚:
- 立即停止MySQL服务
- 恢复原数据目录:
bash复制sudo rm -rf /var/lib/mysql sudo mv /var/lib/mysql_backup /var/lib/mysql - 还原配置文件:
bash复制sudo cp /etc/mysql/mysql.conf.d/mysqld.cnf.bak /etc/mysql/mysql.conf.d/mysqld.cnf - 重启服务:
bash复制sudo systemctl start mysql
建议在维护窗口期进行操作,并准备完整的回滚预案。我在实际迁移中发现,对于超过100GB的大型数据库,使用rsync的--progress参数可以实时观察迁移进度,同时在业务低峰期操作能减少锁表时间。
