恢复mysqldump备份前必须确保目标数据库已存在,因单库备份默认不含create database语句;全库备份除外,但若含drop database需谨慎处理。

恢复 mysqldump 生成的备份,核心前提是:目标数据库必须存在(全库备份除外),且 SQL 文件里没有 DROP DATABASE 或 CREATE DATABASE 语句时,你得自己建库。
mysql 命令导入前必须确认数据库已存在
绝大多数单库备份(如 mysqldump -uroot -p testdb > backup.sql)默认不包含 CREATE DATABASE 语句。直接执行 mysql -uroot -p testdb 会报错:<code>ERROR 1049 (42000): Unknown database 'testdb'。
- 先手动创建空库:
mysql -uroot -p -e "CREATE DATABASE IF NOT EXISTS testdb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" - 字符集建议显式指定,避免与备份中表定义的字符集冲突(尤其当备份未带
--default-character-set=utf8mb4时) - 如果备份用了
--databases参数(例如mysqldump -B testdb),SQL 文件开头会有CREATE DATABASE和USE,此时可跳过建库步骤
恢复时遇到 “Duplicate entry” 或 “Table exists” 错误
这通常是因为目标库中已有同名表,而备份文件里没写 DROP TABLE —— 默认行为就是直接 INSERT,撞了主键或唯一索引就失败。
- 加
--add-drop-table重做备份(推荐):它会在每个CREATE TABLE前插入DROP TABLE IF EXISTS,清旧表再重建 - 临时方案(慎用):在导入前加
-f参数强制继续:mysql -uroot -p -f testdb ,但会跳过出错行,数据可能不完整 - 更安全的做法:先用
mysql -uroot -p testdb -e "SHOW TABLES;"检查现有表,手动DROP TABLE或清空再导入
大备份文件导入慢或中断
mysql 命令默认逐行执行 SQL,遇到几百万行的 INSERT 会卡住、超时,甚至因内存不足崩溃。
- 关掉 autocommit:
mysql -uroot -p testdb -e "SET autocommit=0; SOURCE /path/to/backup.sql; COMMIT;",大幅减少事务提交开销 - 调大服务端参数(需有权限):
max_allowed_packet(防止“Got a packet bigger than ‘max_allowed_packet’ bytes”)、innodb_log_file_size(加速大批量写入) - 拆分大文件:用
split -l 5000 backup.sql chunk_分片,再循环导入;或用sed -n '/^INSERT INTO `table`/,/^;/p' backup.sql提取单表导入 - 别用文本编辑器打开或编辑备份文件——二进制损坏或换行符问题会导致语法错误
恢复后发现中文乱码或时间不准
这不是恢复失败,而是客户端和服务端字符集/时区不一致导致的显示问题。
- 检查备份是否指定了字符集:
head -20 backup.sql | grep "charset",若无,重备时加--default-character-set=utf8mb4 - 导入时显式指定连接字符集:
mysql -uroot -p --default-character-set=utf8mb4 testdb - 验证表实际字符集:
SHOW CREATE TABLE testdb.users;,重点看DEFAULT CHARSET=和COLLATE= - 时区问题:备份里的时间字段(如
DATETIME)是按服务器当前时区写的,恢复后查询显示依赖客户端时区设置,用SELECT @@time_zone, @@session.time_zone;确认
真正容易被忽略的是:备份文件本身是否可执行。有些运维会把 .sql 文件存成 Windows 编码(GBK)或带 BOM,Linux 下导入就会在第一行报语法错误。用 file -i backup.sql 查编码,必要时用 iconv -f gbk -t utf8 backup.sql > backup_utf8.sql 转换。











