在日常数据库运维中,你是否遇到过这样的问题:

系统盘快满了,但业务还在增长

想把热点表放到SSD上提升性能,冷数据留在HDD

某个大库占用了太多空间,影响其他服务

这时候,你可能会想:能不能只把某个表或某个数据库“搬”到另一个磁盘,而不影响整个MySQL实例?

答案是:完全可以!而且根据你使用的存储引擎(InnoDB 还是 MyISAM)、MySQL版本以及运维策略,有多种安全、高效的方式可以实现。今天,我们就来系统梳理 MySQL如何将部分表或库迁移到不同磁盘,并给出实践建议。

1. 为什么需要“部分迁移”?MySQL默认会将所有数据存放在 datadir(通常为 /var/lib/mysql,生产环境一般会调整)目录下。随着业务增长,这个目录可能迅速膨胀,带来以下问题:

磁盘空间不足,导致写入失败

I/O瓶颈集中在一块磁盘,影响整体性能

无法对不同业务数据做存储分级(如热/冷数据分离)

因此,精细化控制数据存储位置,成为高可用、高性能数据库架构的重要一环。

MySQL支持多种存储引擎,但目前主流是 InnoDB(事务、行锁、崩溃恢复),而 MyISAM 已逐渐淘汰(不支持事务、表级锁)。两者的“搬家”方式截然不同。

2. MyISAM 表 —— 简单粗暴但风险高MyISAM 表由三个文件组成:.frm(结构)、.MYD(数据)、.MYI(索引)。你可以直接移动 .MYD 和 .MYI 文件。

2.1 使用 DATA DIRECTORY 和 INDEX DIRECTORY代码语言:javascript复制CREATE TABLE logs (

id INT PRIMARY KEY,

content TEXT

) ENGINE=MyISAM

DATA DIRECTORY = '/ssd/data/'

INDEX DIRECTORY = '/ssd/index/';⚠️ 注意:仅 MyISAM 支持,InnoDB 不识别该语法。

2.2 手动移动 + 符号链接(Symbolic Link)代码语言:javascript复制

停止MySQL(或锁定表)systemctl stop mysql# 移动数据文件mv /var/lib/mysql/mydb/logs.MYD /newdisk/logs.MYDmv /var/lib/mysql/mydb/logs.MYI /newdisk/logs.MYI# 创建软链接ln -s /newdisk/logs.MYD /var/lib/mysql/mydb/logs.MYDln -s /newdisk/logs.MYI /var/lib/mysql/mydb/logs.MYI# 启动MySQLsystemctl start mysql❗ 风险提示:

MySQL 8.0+ 默认禁用符号链接(--skip-symbolic-links);

若权限或路径错误,可能导致表损坏;

不推荐用于生产环境!

3. InnoDB 表 —— 安全、灵活、官方推荐InnoDB 是现代 MySQL 的主力引擎,其“搬家”必须通过表空间(Tablespace) 机制实现。

前提条件:开启 innodb_file_per_table

这是 MySQL 5.6+ 的默认设置,确保每个表有独立的 .ibd 文件:

代码语言:javascript复制SHOW VARIABLES LIKE 'innodb_file_per_table'; -- 应返回 ON3.1 通用表空间(General Tablespace)—— 推荐方式!MySQL 5.7 起引入 通用表空间,允许你自定义 .ibd 文件的存储路径,并支持多个表共享同一空间。步骤如下:

创建位于新磁盘的表空间

代码语言:javascript复制CREATE TABLESPACE `datafiles_1`

ADD DATAFILE '/ssd/mysql/datfile1.ibd'

ENGINE=InnoDB;新建表时指定表空间

代码语言:javascript复制CREATE TABLE test1(

user_id BIGINT,

action VARCHAR(50),

ts TIMESTAMP

) TABLESPACE `datafiles_1`;或将现有表迁入新表空间

代码语言:javascript复制ALTER TABLE your_db.large_table

TABLESPACE `hot_data_ts`;✅ 优点:

路径完全可控支持在线 DDL(MySQL 8.0+)无需停机,安全可靠可用于性能分级(如SSD存热点表)

3.2 表空间迁移(Transportable Tablespaces)—— 适合跨服务器迁移如果你需要将表从一台机器迁到另一台,或临时移动文件,可用此法:

代码语言:javascript复制-- 1. 丢弃原表空间(保留表结构)

ALTER TABLE mydb.mytable DISCARD TABLESPACE;

-- 2. 将 .ibd 文件复制到新位置(如 /ssd/mytable.ibd)

-- 3. 修改权限:

chown mysql:mysql /ssd/mytable.ibd

-- 4. 导入表空间

ALTER TABLE mydb.mytable IMPORT TABLESPACE;⚠️ 注意:需确保 .ibd 与表结构完全一致,且通常要求相同 MySQL 版本。

4. 对比总结:哪种方式更适合你?场景

推荐方案

适用引擎

是否需停机

新建 MyISAM 表存到新盘

DATA DIRECTORY

MyISAM

临时迁移 MyISAM 表

符号链接

MyISAM

建议停机

新建InnoDB 表存新盘

通用表空间

InnoDB

否(MySQL 8.0+)

跨磁盘或服务器迁移 InnoDB 表

DISCARD/IMPORT

InnoDB

部分停写

强烈建议:

如果你还在用 MyISAM,请尽快迁移到 InnoDB如果你用的是 MySQL 5.7 或 8.0+,通用表空间是唯一推荐的“搬家”方式安全提示

操作前务必备份:mysqldump 或 XtraBackup确保新磁盘权限正确:MySQL 用户(通常是 mysql)需有读写权限避免直接修改 datadir:这会影响整个实例,不是“部分迁移”监控 I/O 性能:迁移后验证是否达到预期效果5. 结语数据库“搬家”不是玄学,而是可以通过合理设计实现的运维技能。掌握 通用表空间 和 表空间迁移 技术,不仅能解决磁盘空间问题,还能为你的系统实现 存储分层、性能优化、成本控制 等高级目标。下次当你的磁盘快满了的时候,你就可以自信地说:“别慌,有办法,我们把那张大表搬到其他磁盘上!”