mysqldump 数据迁移:快速导入不同表名 (4种方法)
2025-03-22 04:44:25
使用 mysqldump 将数据导入到不同表中
直接进入正题, 碰到的问题是怎么把 MySQL 一个表的数据导出来,再灌到另一个表里。 两个表的结构都一样,就想把数据挪过去。 已经用 mysqldump
导出了数据, 文件里却有对原表名的引用, 不能直接用. 想找个简单有效的法子, 完成数据迁移。
一、 问题原因分析
mysqldump
默认导出内容包括建表语句和数据插入语句。--no-create-info
参数虽然能去掉建表语句, 但是插入语句里,还是包含了原表名。直接导入到新表,肯定会出错。核心在于导出的 INSERT
语句像这样:
INSERT INTO `users` (...) VALUES (...);
直接导入会把数据插入 users
表,而不是我们想要的 users_new
表。 我们需要的形式是:
INSERT INTO `users_new` (...) VALUES (...);
二、 解决方案
有好几个方法可以解决这个问题。下面一个一个说,每个方法都解释原理,配上代码和使用提示。
1. 使用 --table
参数 和 sed 替换
这是最简单直接的方法,导出的时候不做任何处理,导出后,直接替换文本中的表名。
原理:
sed
是一个流编辑器, 可以用来替换文本。我们可以用它来替换 INSERT
语句中的旧表名为新表名。
操作步骤:
- 导出数据:
```bash
mysqldump -u root -p --no-create-info --skip-add-drop-table --skip-add-locks --skip-disable-keys --quick icicle_db users > users_existing.sql
```
增加下列选项, 加快大表操作:
* `--skip-add-drop-table`: 省略 `DROP TABLE` 语句 (避免误操作)。
* `--skip-add-locks`: 导出过程不加锁.
* `--skip-disable-keys`: 省略禁用/开启索引的操作
* `--quick`: 快速导出大表数据(不一次性加载所有数据到内存).
- 使用
sed
替换表名:
```bash
sed 's/INSERT INTO `users`/INSERT INTO `users_new`/' users_existing.sql > users_new.sql
```
* `s/`: sed 的替换命令的起始。
* `INSERT INTO \`users\``: 要被替换掉的原表名, 包含 "INSERT INTO"。
* `INSERT INTO \`users_new\``: 新的表名,也要加上 `INSERT INTO`.
* `/`: 替换命令的分隔符。
* `users_existing.sql`: 输入文件.
* `users_new.sql`: 输出文件.
- 导入新表:
```bash
mysql -u root -p icicle_db < users_new.sql
```
安全建议:
mysqldump
的--skip-add-locks
选项在生产环境中要小心使用, 确保导出过程不会对业务造成影响。- 正式操作前,先在小数据量表上做测试。
2. 导出时直接使用 sed
这个方法可以把上面导出和替换两个命令合在一起, 一步搞定。
原理:
通过管道把 mysqldump
的输出直接送到 sed
命令处理。
操作步骤:
-
一条命令完成导出和表名替换:
mysqldump -u root -p --no-create-info --skip-add-drop-table --skip-add-locks --skip-disable-keys --quick icicle_db users | sed 's/INSERT INTO `users`/INSERT INTO `users_new`/' > users_new.sql
注意: 这条命令跟上一条命令, 只在于把输出到一个中间文件,改成直接管道处理.
-
导入到新表
mysql -u root -p icicle_db < users_new.sql
3. 使用 mysql
客户端 --execute
可以利用mysql
客户端直接插入。
原理:
我们可以将所有的数据行作为值构建为一个庞大的插入语句。这适用于中小表, 特别简单.
步骤:
-
先查询到需要的数据,并且格式化好,准备作为 values 使用.
SELECT GROUP_CONCAT( CONCAT('(', id, ',', QUOTE(name), ',', -- 处理字符串 QUOTE(email), ')' ) SEPARATOR ',' ) FROM icicle_db.users;
GROUP_CONCAT
: 将查询出的每一行组合成一个字符串, 方便我们组合成VALUES
后面的多个括号组合。CONCAT
: 将每个字段的值, 组成带括号的形式(val1,val2)
QUOTE
: 处理字符串中的特殊字符。避免 SQL 注入.SEPARATOR ','
每个values,之间,使用,
分隔
-
将上面得到的结果(作为值列表),跟
INSERT INTO 新表名
拼起来, 组成完整的 insert 语句 -
使用
mysql
执行这个完整的插入语句:
mysql -u root -p -e "INSERT INTO icicle_db.users_new (id, name, email) VALUES <将第一步执行得到的结果贴到这里> "
-e
: 执行后面的字符串中的SQL语句。
把第一步的结果复制进去就可以.
进阶
第一步产生的values, 默认有最大长度控制。 使用下列方式扩大, 适应超长的单次插入
```sql
-- 先扩大 GROUP_CONCAT 长度
SET group_concat_max_len = 1024 * 1024 * 10; -- 设置为10MB 或更大
-- 然后再运行前面的查询, 生成INSERT语句需要的
SELECT GROUP_CONCAT(
-- .... 其它保持不变 ...
)
);
```
缺点
- 如果数据量过大, 会产生很长的单个语句. 可能会遇到数据库限制
- 需要先导出一次.
4. 使用 LOAD DATA INFILE (进阶技巧)
如果对性能有很高的要求,或者数据量特别大,这个方法是首选. 但是操作稍复杂。
原理:
LOAD DATA INFILE
是 MySQL 导入数据的最快方式之一。
步骤:
-
从原表导出数据到 CSV 文件。
SELECT * INTO OUTFILE '/tmp/users.csv' FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n' FROM icicle_db.users;
INTO OUTFILE
: 指定导出的文件路径。FIELDS TERMINATED BY ','
: 字段之间用逗号分隔。OPTIONALLY ENCLOSED BY '"'
: 字符串字段可以选择用双引号包围。LINES TERMINATED BY '\n'
: 行之间用换行符分隔。- 导出路径通常位于 mysql secure-file-priv 路径, 可以查询:
show variables like '%secure%';
-
将 CSV 文件导入到新表。
LOAD DATA INFILE '/tmp/users.csv' INTO TABLE icicle_db.users_new FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n';
- 文件路徑一定要正确。
安全建议:
- 导出的文件 (
/tmp/users.csv
) 要注意权限, 避免信息泄露。 - 用完后尽快删除临时文件.
进阶:
导出时候,直接指定表名。 这样不需要中间临时文件. mysql
命令行结合 sed
.
mysql -u root -p -N -s -e "SELECT * FROM icicle_db.users" | sed 's/\t/,/g' | mysql -u root -p -D icicle_db -e "LOAD DATA LOCAL INFILE STDIN INTO TABLE users_new FIELDS TERMINATED BY ','"
-N
: 去掉列名.-s
: 简单输出, 非table格式.sed 's/\t/,/g'
: 替换Tab为逗号。LOAD DATA LOCAL INFILE STDIN
:直接从管道输入.
* 此种用法有客户端版本和配置限制,需要local_infile=1
在 my.cnf, 客户端也允许该功能。
可以添加下列设置来调整性能
```sql
SET unique_checks=0;
SET foreign_key_checks=0;
-- 插入数据 ...
SET unique_checks=1;
SET foreign_key_checks=1;
```
总结
以上就是几种迁移数据的方法,各有优缺点,根据情况选一种就行:
- 简单替换:适合中小表,数据量不大的。
- 管道处理:跟上面差不多,减少一步文件操作.
- 客户端组装INSERT:适合需要处理某些复杂条件.
LOAD DATA INFILE
:大数据量下首选,性能最好。