Skip to content
Charles
Go back

MySQL 导入导出数据

Edit page

MySQL 的“导入导出”其实对应几种不同需求:迁移完整数据库、备份后恢复、交换 CSV 文件,或者只导出满足条件的一部分数据。先选对工具,通常比给命令加一堆参数更重要。

本文示例使用以下变量:

主机:127.0.0.1
端口:3306
数据库:app_db
用户:backup

命令中的 -p 会交互式提示输入密码,不要把真实密码直接写在命令行或脚本里。

先看怎么选

场景导出方式导入方式
完整迁移、日常备份mysqldumpmysql
迁移单个表或部分行mysqldump --wheremysql
与 Excel、Python 等工具交换文件SELECT ... INTO OUTFILELOAD DATA
已有 CSV/TSV 文件文件本身LOAD DATAmysqlimport
数据量很大,需要并行导入导出MySQL Shell Dump UtilityMySQL Shell util.loadDump()

如果目标是“把数据库完整搬到另一台 MySQL”,优先使用 SQL dump;如果目标是“给其他程序一个文件”,使用 CSV/TSV 更合适。

使用 mysqldump 导出 SQL

导出一个数据库

mysqldump \
  -h 127.0.0.1 \
  -P 3306 \
  -u backup \
  -p \
  --single-transaction \
  --routines \
  --events \
  --triggers \
  --default-character-set=utf8mb4 \
  app_db > app_db.sql

这会把表结构和表数据写成 SQL 文件。--routines--events--triggers 用于显式包含存储过程、事件和触发器,避免迁移后只剩下表和数据。

对主要使用 InnoDB 的库,--single-transaction 可以在不长时间锁表的情况下获得一致性快照。它不等于对所有存储引擎都提供一致性:MyISAM 等非事务表仍应安排停写、锁表或使用其他备份方案;导出过程中也不要同时执行会改变表结构的 DDL。

导出多个数据库或全部数据库

# 导出指定的多个数据库,同时写入 CREATE DATABASE 和 USE
mysqldump -h 127.0.0.1 -u backup -p \
  --databases app_db audit_db > databases.sql

# 导出实例中的全部数据库
mysqldump -h 127.0.0.1 -u backup -p \
  --all-databases > all-databases.sql

--databases--all-databases 生成的文件通常自带创建数据库和切换数据库的语句。单数据库命令 mysqldump app_db 则不会自动创建目标数据库,导入时需要手动指定数据库。

只导出表结构或只导出数据

# 只导出表结构,不导出行数据
mysqldump -h 127.0.0.1 -u backup -p \
  --no-data app_db > app_db-schema.sql

# 只导出数据,不导出 CREATE TABLE
mysqldump -h 127.0.0.1 -u backup -p \
  --no-create-info app_db > app_db-data.sql

这两个选项适合测试环境初始化,或者需要先手工调整表结构、再加载数据的场景。

只导出指定的表

mysqldump -h 127.0.0.1 -u backup -p \
  --single-transaction app_db users orders > selected-tables.sql

表名写在数据库名后面即可。导出视图、触发器或其他对象时,要根据迁移范围显式检查对应选项和权限。

按条件导出部分数据

mysqldump -h 127.0.0.1 -u backup -p \
  --single-transaction \
  app_db orders \
  --where="created_at >= '2026-01-01'" > orders-2026.sql

--where 会把条件附加到导出数据的查询中。条件中的日期、状态等值应来自可信配置,并在执行前确认不会误导出或漏导数据。

压缩导出文件

mysqldump -h 127.0.0.1 -u backup -p \
  --single-transaction app_db | gzip > app_db.sql.gz

恢复时直接解压到 mysql 命令即可,不必先生成中间文件:

gzip -dc app_db.sql.gz | mysql -h 127.0.0.1 -u backup -p app_db

导入 SQL 文件

导入到已有数据库

mysql -h 127.0.0.1 -P 3306 -u backup -p app_db < app_db.sql

如果 app_db 还不存在,先创建数据库,并明确指定字符集:

mysql -h 127.0.0.1 -u root -p \
  -e "CREATE DATABASE IF NOT EXISTS app_db CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;"

mysql -h 127.0.0.1 -u backup -p app_db < app_db.sql

也可以登录 MySQL 后执行:

CREATE DATABASE IF NOT EXISTS app_db
  CHARACTER SET utf8mb4
  COLLATE utf8mb4_0900_ai_ci;

USE app_db;
SOURCE /backup/app_db.sql;

如果 dump 文件是用 --databases--all-databases 生成的,文件里已经包含 CREATE DATABASEUSE,导入时可以不指定默认数据库:

mysql -h 127.0.0.1 -u root -p < all-databases.sql

从一台服务器直接传到另一台

不想落地中间文件时,可以使用管道:

mysqldump -h source.example.com -u backup -p \
  --single-transaction app_db \
  | mysql -h target.example.com -u backup -p app_db

两端的 MySQL 版本、字符集、SQL mode 和表结构应提前确认。生产环境迁移建议先导入临时数据库,完成校验后再切换业务连接,避免导入失败后留下半成品数据。

导出和导入 CSV/TSV

SQL dump 适合 MySQL 到 MySQL;如果需要给其他程序处理,通常导出为 CSV 或 TSV。

使用 SELECT INTO OUTFILE 导出

SELECT id, name, created_at
INTO OUTFILE '/var/lib/mysql-files/users.csv'
CHARACTER SET utf8mb4
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
FROM users
ORDER BY id;

这里有几个容易忽略的事实:

如果只想把查询结果保存到当前客户端机器,也可以使用客户端重定向:

mysql -h 127.0.0.1 -u backup -p -D app_db \
  --batch --raw \
  -e "SELECT id, name, created_at FROM users ORDER BY id" \
  > users.tsv

这种方式输出的是制表符分隔文本,适合简单交换;需要严格控制 CSV 引号和换行时,优先使用 INTO OUTFILE 的格式选项。

使用 LOAD DATA 导入

假设 users.csv 第一行是表头,字段顺序为 id,name,created_at

LOAD DATA LOCAL INFILE '/path/to/users.csv'
INTO TABLE users
CHARACTER SET utf8mb4
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 LINES
(id, name, @created_at)
SET created_at = NULLIF(@created_at, '');

LOCAL 表示文件位于客户端主机。Windows 导出的文件通常使用 \r\n 换行,此时应把 LINES TERMINATED BY '\n' 改成 LINES TERMINATED BY '\r\n'

MySQL 8.x 默认可能关闭本地文件加载,需要客户端和服务端同时允许:

mysql --local-infile=1 -h 127.0.0.1 -u backup -p app_db

服务端可检查当前配置:

SHOW VARIABLES LIKE 'local_infile';

只对可信文件和可信服务器开启 LOCAL。不需要批量导入时,保持关闭更安全;如果确实要开启,导入完成后应恢复原来的设置。

使用 mysqlimport

mysqlimportLOAD DATA 的命令行封装。它会根据文件名(去掉扩展名)寻找目标表,所以 users.csv 默认对应 users 表:

mysqlimport \
  --local \
  --ignore-lines=1 \
  --columns=id,name,created_at \
  --fields-terminated-by=',' \
  --fields-optionally-enclosed-by='"' \
  --lines-terminated-by='\n' \
  -h 127.0.0.1 -u backup -p \
  app_db users.csv

字段分隔符、包围符和换行符必须与文件实际格式一致,否则常见结果是列错位、中文乱码或整行导入失败。

字符集和权限

统一使用 utf8mb4

导入导出前可以检查连接和服务端字符集:

SHOW VARIABLES LIKE 'character_set%';
SHOW VARIABLES LIKE 'collation%';

实践中建议统一以下几层:

  1. 数据库和表使用 utf8mb4
  2. mysqldump 增加 --default-character-set=utf8mb4
  3. CSV 导入导出明确写出 CHARACTER SET utf8mb4
  4. 连接客户端、应用程序和终端也使用 UTF-8。

不要用 latin1 去“修复”乱码。乱码通常是数据已经被错误解码或重复转码,先确认原文件编码和连接字符集,再决定是否转换。

导出账号不等于导出数据库

普通的 mysqldump app_db 主要导出数据库对象和数据,不会自动把业务账号、密码和授权关系迁移到目标实例。迁移前至少检查:

SHOW GRANTS FOR 'backup'@'%';

账号和授权应在目标环境按最小权限重新创建,不要为了导入方便直接给业务用户 ALL PRIVILEGES 或使用 root。

导入后的校验

命令执行成功只是第一步,至少做一次行数和关键范围校验:

SELECT COUNT(*) AS row_count, MIN(id) AS min_id, MAX(id) AS max_id
FROM users;

SELECT COUNT(*) AS row_count, MIN(created_at) AS first_created_at,
       MAX(created_at) AS last_created_at
FROM orders;

还应抽查:

不要随意使用 mysql --force 忽略导入错误。它可能让命令看起来执行完成,但数据库已经处于部分导入状态;正确做法是保留错误输出,修复原因后重新导入或丢弃临时数据库重来。

大数据量场景

mysqldump 简单可靠,几十 GB 以上的库则需要关注磁盘、网络和导入时长。可以先尝试压缩管道;如果仍然太慢,再使用 MySQL Shell 的 Dump Utility,它支持并行导出、分片文件、压缩和并行加载:

// 在源库连接上执行
util.dumpSchemas(["app_db"], "/backup/app_db", { threads: 4 });

// 在目标库连接上执行
util.loadDump("/backup/app_db", { threads: 4 });

并行不等于可以忽略一致性和资源上限。执行前确认备份目录为空、目标实例有足够磁盘空间,并观察 CPU、磁盘 IO、连接数和 InnoDB 日志压力。数据一致性仍取决于表使用的存储引擎和执行期间的写入、DDL 行为。

一套可复用的迁移流程

# 1. 导出
mysqldump -h source.example.com -u backup -p \
  --single-transaction \
  --routines --events --triggers \
  --default-character-set=utf8mb4 \
  app_db | gzip > app_db.sql.gz

# 2. 检查压缩文件
gzip -t app_db.sql.gz

# 3. 创建临时数据库
mysql -h target.example.com -u root -p \
  -e "CREATE DATABASE app_db_import CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;"

# 4. 导入临时数据库
gzip -dc app_db.sql.gz | \
  mysql -h target.example.com -u backup -p app_db_import

导入后完成行数、关键业务数据和应用连接校验,再安排切换。不要把“生成了一个 .sql 文件”当成备份完成:没有经过恢复测试的备份,不能证明真的可恢复。

总结

参考资料


Edit page
Share this post:

Previous Post
S3 对象存储方案对比
Next Post
vscode 全键盘操作