使用命令行导入和导出MySQL数据库
掌握从命令行进行MySQL数据库导入和导出操作,是任何数据库管理员或后端工程师不可或缺的技能。`mysqldump`工具将数据库导出为可移植的`.sql`文件,其中包含完整重建架构和数据所需的所有DDL和DML语句,而`mysql`客户端命令则处理相反的操作——将该文件流式传输回正在运行的MySQL实例。
本指南涵盖所有实际场景:单数据库导出、多数据库转储、仅结构备份、压缩传输、字符集处理以及安全导入工作流——包括在生产环境中导致静默数据损坏或恢复失败的边缘情况。
前提条件
在执行本指南中的任何命令之前,请验证以下内容:
- MySQL Server(5.7、8.0或8.4)已安装且`mysqld`进程正在运行
- `mysqldump`和`mysql`二进制文件位于系统`PATH`中(使用`which mysqldump`确认)
- 您持有的MySQL账户至少具有导出所需的`SELECT`、`LOCK TABLES`、`SHOW VIEW`和`TRIGGER`权限;导入所需的`CREATE`、`INSERT`、`ALTER`和`DROP`权限
- 目标位置有足够的磁盘空间——压缩转储在导入时可能扩展5–10倍
- 您拥有服务器的shell访问权限(本地终端、SSH或托管的VPS Hosting环境)
使用mysqldump导出数据库
`mysqldump`是MySQL捆绑的标准逻辑备份工具。它将数据库对象序列化为人类可读的SQL脚本。与Percona XtraBackup等物理备份工具不同,`mysqldump`与存储引擎无关,可跨MySQL版本甚至MariaDB分支使用。
1. 导出单个数据库
“`bash
mysqldump -u [username] -p [database_name] > [filename].sql
“`
参数说明:
- `-u [username]` — 用于连接的MySQL账户
- `-p` — 触发交互式密码提示(切勿在共享系统上以`-p[password]`方式内联传递密码;它在`ps aux`输出中可见)
- `[database_name]` — 要导出的目标架构
- `> [filename].sql` — 将标准输出重定向到输出文件
示例:
“`bash
mysqldump -u root -p mydatabase > mydatabase_backup.sql
“`
这将生成一个包含`CREATE TABLE`、`INSERT`和`ALTER TABLE`语句的文件,足以从头重建`mydatabase`。
关键边缘情况:默认情况下,`mysqldump`在转储开始时会获取全局读锁(`FLUSH TABLES WITH READ LOCK`)。在高流量InnoDB服务器上,请改用`–single-transaction`以在不阻塞写入的情况下获取一致快照:
“`bash
mysqldump -u root -p –single-transaction mydatabase > mydatabase_backup.sql
“`
`–single-transaction`仅在InnoDB表上可靠运行。如果您的数据库包含MyISAM表,则锁定是不可避免的。
2. 导出多个数据库
“`bash
mysqldump -u [username] -p –databases db1 db2 > multiple_databases_backup.sql
“`
`–databases`标志指示`mysqldump`在输出中包含`CREATE DATABASE`和`USE`语句,使转储自包含。如果没有此标志,这些语句将被省略,转储将假定在导入时已选择目标数据库。
示例:
“`bash
mysqldump -u root -p –databases db1 db2 > multiple_databases_backup.sql
“`
3. 导出所有数据库
“`bash
mysqldump -u root -p –all-databases > all_databases_backup.sql
“`
这将导出连接用户可以访问的每个架构,包括`mysql`、`information_schema`和`performance_schema`系统数据库。避免跨主要MySQL版本边界导入系统数据库——MySQL 5.7和8.0之间的权限表架构发生了重大变化,将旧的`mysql`架构导入全新的8.0实例将损坏身份验证。
要排除系统架构:
“`bash
mysqldump -u root -p –all-databases
–ignore-table=mysql.user
–ignore-table=mysql.db
> all_user_databases_backup.sql
“`
4. 仅导出表结构(无数据)
“`bash
mysqldump -u root -p –no-data mydatabase > structure_only.sql
“`
这对于架构版本控制、代码审查或搭建空白暂存环境非常有价值。输出仅包含`CREATE TABLE`、`CREATE VIEW`、`CREATE PROCEDURE`及类似的DDL——不含`INSERT`行。
5. 导出特定表
“`bash
mysqldump -u root -p mydatabase table1 table2 > tables_backup.sql
“`
请注意,以这种方式导出特定表时,`mysqldump`不包含`CREATE DATABASE`或`USE`语句。您必须确保目标数据库在导入前已存在。
6. 导出存储过程、触发器和事件
默认情况下,`mysqldump`包含触发器,但省略存储过程、函数和计划事件。要进行完整的应用程序备份:
“`bash
mysqldump -u root -p
–routines
–triggers
–events
–single-transaction
mydatabase > full_backup.sql
“`
忘记`–routines`是导致应用程序恢复失败最常见的原因之一——架构和数据存在,但业务逻辑丢失。
7. 压缩导出
将输出直接通过`gzip`管道传输,可将文件大小减少60–80%:
“`bash
mysqldump -u root -p mydatabase | gzip > mydatabase_backup.sql.gz
“`
对大型数据库进行最大压缩(以CPU时间为代价):
“`bash
mysqldump -u root -p mydatabase | gzip -9 > mydatabase_backup.sql.gz
“`
使用mysql客户端导入数据库
`mysql`命令行客户端通过stdin重定向接受SQL文件,并针对目标服务器按顺序执行每条语句。
1. 导入到现有数据库
“`bash
mysql -u [username] -p [database_name] < [filename].sql
“`
示例:
“`bash
mysql -u root -p mydatabase < mydatabase_backup.sql
“`
重要提示:如果`.sql`文件是使用`–databases`或`–all-databases`导出的,它已经包含`CREATE DATABASE`和`USE`指令。在这种情况下,不要在命令行上指定数据库名称——这样做会产生冲突:
“`bash
mysql -u root -p < all_databases_backup.sql
“`
2. 导入到新数据库
目标数据库必须在导入之前存在。MySQL不会从裸表转储中自动创建它。
步骤1 — 创建数据库:
“`bash
mysql -u root -p -e "CREATE DATABASE newdatabase CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
“`
步骤2 — 导入转储:
“`bash
mysql -u root -p newdatabase < mydatabase_backup.sql
“`
始终在创建数据库时明确指定字符集和排序规则。依赖服务器默认值是编码不匹配的常见原因,尤其是在具有不同`character_set_server`配置的服务器之间迁移时。
3. 导入压缩转储
“`bash
gunzip < mydatabase_backup.sql.gz | mysql -u root -p mydatabase
“`
或使用`zcat`(在大多数Linux发行版上等效):
“`bash
zcat mydatabase_backup.sql.gz | mysql -u root -p mydatabase
“`
4. 带进度监控的导入
对于大型转储,标准`mysql`客户端不提供任何反馈。使用`pv`(管道查看器)显示实时进度条:
“`bash
pv mydatabase_backup.sql | mysql -u root -p mydatabase
“`
使用`apt install pv`或`yum install pv`安装`pv`。在处理多GB级生产数据库的Dedicated Server上,这种可见性在运营上至关重要。
mysqldump与其他备份方法的比较
| 功能 | mysqldump | mysqlpump | MySQL Shell (util.dumpInstance) | Percona XtraBackup |
|---|
| — | — | — | — | — |
|---|
| 备份类型 | 逻辑(SQL) | 逻辑(SQL) | 逻辑(JSON/SQL) | 物理(二进制) |
|---|
| 并行性 | 单线程 | 多线程 | 多线程 | 多线程 |
|---|
| InnoDB热备份 | 使用`–single-transaction` | 使用`–single-transaction` | 是 | 是 |
|---|
| 输出格式 | 纯SQL | 纯SQL | 分块文件 | 原始InnoDB文件 |
|---|
| 恢复速度 | 慢(顺序SQL) | 中等 | 快 | 非常快 |
|---|
| 跨版本可移植性 | 优秀 | 良好 | 良好 | 仅限相同主版本 |
|---|
| 包含在MySQL中 | 是 | 是(5.7.8+) | 需单独安装 | 第三方 |
|---|
| 最佳使用场景 | 可移植性、中小型数据库 | 并行转储 | 云/大型架构 | 大型生产数据库 |
|---|
对于在托管的VPS with cPanel上运行多个生产数据库的环境,`mysqldump`由于其兼容性和简单性,仍然是最广泛支持的选项。
高级配置和边缘情况
正确处理字符集
字符集不匹配是导致导入损坏的不成比例的主要原因。最安全的方法是在每个阶段都明确指定:
“`bash
mysqldump -u root -p
–default-character-set=utf8mb4
mydatabase > mydatabase_backup.sql
“`
“`bash
mysql -u root -p
–default-character-set=utf8mb4
mydatabase < mydatabase_backup.sql
“`
注意:MySQL中的`utf8`是一个3字节子集,无法存储4字节Unicode字符(表情符号、某些CJK表意文字)。新数据库始终使用`utf8mb4`。
加速大型导入
默认情况下,MySQL在转储中的每条`INSERT`语句后执行完整提交。对于大型数据集,这会极其缓慢。在导入会话开始时添加以下内容:
“`bash
mysql -u root -p mydatabase <<EOF
SET foreign_key_checks = 0;
SET unique_checks = 0;
SET autocommit = 0;
SOURCE /path/to/mydatabase_backup.sql;
COMMIT;
SET foreign_key_checks = 1;
SET unique_checks = 1;
EOF
“`
或者,使用`–extended-insert`(默认启用)和`–disable-keys`导出,以批量插入并在数据加载后延迟索引重建。
使用Cron自动化备份
`/etc/cron.d/mysql-backup`中的生产级自动备份条目:
“`bash
0 2 * * * root mysqldump -u backup_user -p'StrongPass'
–single-transaction –routines –triggers –events
mydatabase | gzip > /backups/mydatabase_$(date +%F).sql.gz
“`
使用具有最低所需权限的专用MySQL用户,而不是`root`。使用以下命令创建:
“`sql
CREATE USER 'backup_user'@'localhost' IDENTIFIED BY 'StrongPass';
GRANT SELECT, LOCK TABLES, SHOW VIEW, TRIGGER, EVENT ON *.* TO 'backup_user'@'localhost';
FLUSH PRIVILEGES;
“`
使用.my.cnf保护凭据
在命令行上传递密码会将其暴露在shell历史记录和进程列表中。将凭据存储在`~/.my.cnf`中:
“`ini
[client]
user=root
password=YourSecurePassword
“`
立即设置权限:
“`bash
chmod 600 ~/.my.cnf
“`
完成此设置后,所有`mysqldump`和`mysql`命令将自动获取凭据,无需`-u`和`-p`标志。
远程数据库导出
从远程MySQL服务器转储数据库:
“`bash
mysqldump -h remote.server.com -P 3306 -u remoteuser -p remotedatabase > remote_backup.sql
“`
确保远程MySQL实例允许来自您IP地址的连接,并且防火墙中端口3306已开放。对于加密传输,通过SSH隧道:
“`bash
ssh -L 3307:127.0.0.1:3306 user@remote.server.com -N &
mysqldump -h 127.0.0.1 -P 3307 -u remoteuser -p remotedatabase > remote_backup.sql
“`
实用决策矩阵
| 场景 | 推荐命令 |
|---|
| — | — |
|---|
| 完整备份,仅InnoDB,无停机 | `mysqldump –single-transaction –routines –triggers –events` |
|---|
| 架构迁移到新服务器 | `mysqldump –no-data` + 重建数据库 + 导入 |
|---|
| 在服务器之间移动单个数据库 | `mysqldump db | gzip | ssh user@dest "gunzip | mysql db"` |
|---|
| 备份所有数据库,排除系统架构 | `–all-databases` + `–ignore-table`用于系统表 |
|---|
| 快速恢复大型转储 | 禁用`foreign_key_checks`、`unique_checks`、`autocommit` |
|---|
| 自动夜间备份 | Cron + 专用备份用户 + `.my.cnf`凭据 |
|---|
| 验证备份完整性 | 导入到测试数据库并运行`SHOW TABLE STATUS` |
|---|
关键技术要点
- 对InnoDB数据库始终使用`–single-transaction`,以避免在导出期间阻塞应用程序写入
- 始终明确指定`utf8mb4`——切勿依赖服务器默认字符集假设
- 在每次完整应用程序备份中包含`–routines`、`–triggers`和`–events`,否则可能丢失业务逻辑
- 切勿跨主要MySQL版本边界导入系统架构表(`mysql.*`)
- 将凭据存储在具有`chmod 600`权限的`~/.my.cnf`中——切勿将密码作为内联参数传递
- 对于超过10 GB的数据库,评估`mysqlpump`或MySQL Shell的并行转储工具,因为`mysqldump`将成为瓶颈
- 在依赖备份进行灾难恢复之前,通过在隔离环境中执行测试恢复来验证每个备份
- 托管多个客户端数据库时,使用独立的VPS Control Panels隔离环境,以防止恢复操作期间的跨租户访问
- 将数据库备份策略与连接到MySQL的任何面向Web的应用层上的有效SSL Certificate配合使用,以防止传输中的凭据拦截
常见问题
mysqldump和mysqlpump有什么区别?
`mysqldump`是单线程的,生成单个SQL文件——可靠且具有普遍兼容性。`mysqlpump`在MySQL 5.7.8中引入,支持同时并行导出多个数据库和表,显著减少多核服务器上的转储时间。但是,`mysqlpump`在混合引擎数据库的一致备份方面存在已知问题,不太适合跨版本迁移。
我可以将MySQL 5.7转储导入MySQL 8.0吗?
可以,但有注意事项。用户数据和应用程序架构可以干净地导入。但是,切勿直接导入`mysql`系统数据库——身份验证插件在8.0中从`mysql_native_password`更改为`caching_sha2_password`,导入旧的权限表将破坏身份验证。使用`CREATE USER`和`GRANT`语句手动重建用户。
为什么我的导入因外键约束而失败,提示”ERROR 1005: Can’t create table”?
当表以违反外键依赖关系的顺序导入时会发生这种情况。解决方法是在导入会话前添加`SET foreign_key_checks = 0;`,并在完成后追加`SET foreign_key_checks = 1;`。或者,使用`–single-transaction`导出,它在转储文件本身中保留引用完整性。
如何仅导出数据而不包含CREATE TABLE语句?
使用`–no-create-info`标志:`mysqldump -u root -p –no-create-info mydatabase > data_only.sql`。当您需要将数据重新加载到现有架构中而不更改其结构时,这非常有用。
在两个远程服务器之间传输MySQL转储最安全的方式是什么?
通过SSH直接管道传输转储,无需将中间文件写入磁盘:`mysqldump -u root -p sourcedb | ssh user@destination.server "mysql -u root -p targetdb"`。这比复制纯文本`.sql`文件更快、更安全,尤其是在磁盘配额受限的Shared Web Hosting环境中运行时。
