直接迁移数万张微型表时,mysqldump会因频繁打开/关闭文件句柄触发“too many open files”错误或被系统kill;必须改用mydumper+myloader多线程方案,或满足严格条件时采用物理拷贝,同时导入阶段需调优事务粒度、禁用约束检查并校验表完整性。

直接迁移数万张微型表(每张表几KB~几百KB)的 MySQL 实例,mysqldump 单线程导出会卡在打开/关闭文件句柄上,极易触发 Too many open files 错误或进程被系统 kill。这不是数据量问题,而是表数量引发的 OS 层资源瓶颈——必须绕开“逐表 fopen/fclose”这个路径。
为什么 mysqldump 会崩在数万张表上
默认情况下,mysqldump 对每个表都会单独执行一次 SELECT 并写入输出流,内部会为每个表临时打开文件描述符(尤其启用 --single-transaction 或 --lock-tables=false 时)。Linux 默认 ulimit -n 是 1024,而数万张表远超此限;即使调高 ulimit,glibc 的 FILE* 缓存和 MySQL 客户端连接层也会因频繁 fd 切换出现性能断崖。
常见错误现象:
mysqldump: Got error: 23: Out of resources when opening file './db1/t_12345.frm' (Errcode: 24)- 导出中途静默退出,无报错但 SQL 文件不完整
- 目标库导入时提示
ERROR 1105 (HY000): Unknown error,实为源端未正确 flush 表定义
用 mydumper + myloader 替代 mysqldump
mydumper 是专为高表数量场景设计的多线程逻辑备份工具,它把“表发现 → 分配线程 → 并行 dump”拆开,每个 worker 线程复用同一个数据库连接,并按批(而非每表)管理文件句柄;myloader 导入时也支持并发建表+加载,避免单点阻塞。
实操建议:
- 安装时确认版本匹配:MySQL 8.0+ 建议用
mydumper 0.11.3+,旧版对mysql.ibd元数据处理有缺陷 - 导出命令加
--no-schemas(如果只迁业务库,跳过mysql系统库),并用--threads=8控制并发(别盲目设太高,8~16 足够压满千兆网卡) - 务必加
--skip-tz-utc,否则跨时区服务器可能因TIMESTAMP转换导致数据偏移 - 导出后检查
metadata文件里的Finished dump at:时间戳是否完整,这是判断 dump 是否中途失败的关键依据
物理拷贝仅适用于同版本、同架构、且表全为 InnoDB 的场景
如果你确认所有微型表都是 InnoDB 引擎、且没用 MyISAM / FEDERATED / 分区表等特殊类型,可考虑停机后直接拷贝 .ibd 文件——但必须满足:innodb_file_per_table=ON(默认开启),且目标实例 server_uuid 与源不同(防复制冲突)。
关键风险点:
- 拷贝前必须执行
FLUSH TABLES WITH READ LOCK+SHOW MASTER STATUS记下 binlog 位置,否则无法做一致性恢复 - 拷贝后首次启动目标实例时,若遇到
Tablespace is missing for table `db`.`t1`,说明ibdata1中未注册该表空间,需用ALTER TABLE ... IMPORT TABLESPACE手动挂载(极耗时,数万张表不可行) - MySQL 8.0 的数据字典表(
mysql.schemata,mysql.tables)是事务表,不能直接拷.ibd,必须用mydumper或 XtraBackup
导入阶段防止 myloader 卡死或 OOM
myloader 默认每张表一个事务,数万张表意味着数万个 COMMIT,不仅慢还会撑爆 buffer pool。必须调整参数:
- 用
--queries-per-transaction=1000合并插入语句,减少事务提交次数 - 禁用目标库唯一性检查:
SET FOREIGN_KEY_CHECKS=0; SET UNIQUE_CHECKS=0;(在导入前手动执行) - 导入前删掉非必要索引,等数据加载完再重建(
myloader不支持延迟建索引,得自己写脚本 post-process) - 监控
SHOW PROCESSLIST,若看到大量Waiting for table metadata lock,说明某张表正在被其他连接持有元数据锁,需杀掉干扰连接
真正容易被忽略的是:数万张微型表往往来自分表逻辑(如按日期/用户ID哈希),这类结构在导入后必须立刻校验表名连续性和空表比例——mydumper 遇到空表可能跳过 dump,但不会报错,结果就是目标库少几百张表,业务查不到数据却无任何异常日志。











