识别非标准备份需先用file或head查看文件头:insert/create开头为mysqldump;逗号分隔无sql关键字为csv;/*!40101或-- host为mysqldump注释;---或insert ignore为mydumper。

备份文件不是 mysqldump 标准格式,怎么识别它?
先别急着导入,得确认你手里的备份到底是什么——常见非标准备份包括:直接拷贝的 data/ 目录、SELECT ... INTO OUTFILE 生成的纯文本、mydumper 的分表输出、甚至某业务脚本拼的 CSV。用 file 命令或 head -n 5 backup.sql 看前几行最靠谱:INSERT INTO 或 CREATE TABLE 开头大概率是 mysqldump;全是逗号分隔、没 SQL 关键字,基本是 CSV;看到 /*!40101 SET 或 -- Host: 注释,就是 mysqldump;如果开头是 --- 或 INSERT IGNORE 批量写法,可能是 mydumper。
用 LOAD DATA INFILE 导入 CSV 类备份时要注意什么?
这是最快也最容易翻车的方式。它不走 SQL 解析器,直接读文件进表,所以字段顺序、分隔符、NULL 表示必须和表结构严丝合缝。
-
LOAD DATA INFILE要求文件在 MySQL 服务端路径(不是你本地),用LOCAL版本需客户端和服务端都开启local_infile=ON,且 MySQL 8.0+ 默认禁用,得加启动参数或改配置 - 字段数不匹配会报错
Error 1261: Row 1 doesn’t contain data for all columns,用SET @var := NULL配合SET子句跳过多余列,或提前用sed/awk清洗文件 - 日期字段含
"2023-01-01"这种带引号的,得加FIELDS ENCLOSED BY '"';空字符串要转成\N才被识别为 NULL - 大文件导入前建议关掉唯一键检查:
SET unique_checks=0;,完事再开,否则每行都校验索引,慢十倍不止
写 Python 脚本解析自定义备份并批量插入,选 mysql-connector-python 还是 pymysql?
两者都能用,但差别在连接稳定性与错误处理粒度:pymysql 纯 Python 实现,调试方便,对非标准 SQL 字符串容错略高;mysql-connector-python 官方驱动,事务控制更稳,但遇到编码异常(比如备份里混了 latin1 和 utf8mb4)容易静默截断。实际选 pymysql 更省心,尤其你要自己 parse 文本时。
- 务必用
executemany()批量插入,别写 for 循环单条execute(),性能差一个数量级 - 遇到
1366: Incorrect string value,不是简单改连接 charset 就行,得先用chardet检测文件真实编码,再 decode 后 encode 成utf8mb4 - 表名、字段名来自备份文件头?别直接拼 SQL,用
cursor.execute("INSERT INTO `%s` (...) VALUES (...)", (table_name, ...)),反引号防关键字冲突,参数化防注入
恢复后数据对不上,怎么快速定位哪一行出问题?
别一上来就重跑全量。先比行数:SELECT COUNT(*) FROM tbl vs wc -l backup.csv(减去 header 行);再抽样查几条关键记录的主键值,用 SELECT * FROM tbl WHERE id IN (1001, 1002, 1003) 看内容是否和备份里一致。最容易漏的是:时间字段被自动转换时区(MySQL 服务端 time_zone 和备份生成时不同)、浮点数精度丢失(CSV 里 0.1 存成 0.100000001)、以及备份里用 REPLACE INTO 逻辑,而你脚本用了 INSERT IGNORE,导致重复键时行为不一致。
真正麻烦的不是脚本写不对,而是备份本身没记录元信息:没存表结构版本、没标字符集、没写生成时间。下次备份时,顺手 echo 一句 mysqldump --version && mysql --version && date 到同目录下的 backup.meta 里,能省掉一半排查时间。











