mysqldump 默认不导出 ON DELETE CASCADE 等级联规则,需显式添加 --complete-insert、--add-drop-table、--disable-keys 等参数;pg_dump 需根据场景选择是否加 --clean;SQLite 的 .dump 不含外键定义,须手动提取或用脚本生成。
mysqldump 怎么导出外键约束和级联规则
默认 mysqldump 不会导出外键定义里的 on delete cascade、on update set null 这类级联行为,只保留外键引用关系本身。这是因为它的默认模式是兼容性优先,把约束拆成两步:先建表(不带约束),再用 alter table 加外键——而级联子句在部分老版本 mysql 中可能被忽略或截断。
要完整保留,必须显式启用约束生成开关:
- 加
--skip-tz-utc防止时区干扰(非必需但建议) - 必须加
--complete-insert,否则 INSERT 语句字段顺序可能错乱,影响后续导入时的外键校验 - 最关键的是加
--add-drop-table --add-locks --disable-keys --set-charset组合,确保导入时约束能按预期重建 - 如果目标库版本 ≥ 5.6.4,推荐额外加
--skip-create-options,避免ROW_FORMAT等无关参数干扰外键解析
示例命令:
mysqldump -u root -p --databases mydb --single-transaction --routines --triggers --events --complete-insert --add-drop-table --disable-keys --set-charset > backup.sql
PostgreSQL pg_dump 要不要加 --clean 或 --if-exists
pg_dump 默认不包含 DROP 语句,所以即使你导出了完整的外键 + 级联(如 ON DELETE CASCADE),还原时若表已存在,新约束不会自动覆盖旧约束——旧的级联规则可能残留,导致行为不一致。
是否加 --clean 取决于还原场景:
- 用于初始化新环境(如测试库):直接加
--clean,它会生成DROP TABLE IF EXISTS和CREATE TABLE,级联规则随建表语句一起重建,最安全 - 用于增量同步或补丁式更新:别加
--clean,改用--inserts+ 手动检查ALTER TABLE ... ADD CONSTRAINT是否含ON DELETE子句 -
--if-exists必须配合--clean使用,否则DROP报错中断;单独用没意义
验证导出文件里是否有级联:搜索 ON DELETE 或 ON UPDATE,确认它们出现在 FOREIGN KEY 定义行内,而不是被注释或丢弃。
SQLite 的 PRAGMA foreign_keys=ON 不等于有级联
SQLite 支持外键,但**默认关闭**,且即使开启,也只支持 ON DELETE CASCADE 和 ON DELETE SET NULL,不支持 ON UPDATE CASCADE(会静默忽略)。更关键的是:sqlite3 .dump 命令输出的 SQL **完全不包含外键定义**——它只导出 CREATE TABLE 语句,所有 FOREIGN KEY (...) ON DELETE ... 全部丢失。
必须换方式导出:
- 不用
.dump,改用SELECT sql FROM sqlite_master WHERE type='table'手动提取建表语句,再拼上外键约束(需提前查PRAGMA foreign_key_list(tablename)) - 或者用 Python +
sqlite3模块写个简短脚本,遍历所有表,调用PRAGMA foreign_key_list获取级联动作,动态组装完整 DDL - 第三方工具如
sqlitestudio或DB Browser for SQLite的导出功能通常支持勾选“包含外键”,但得实测是否保留ON子句
一个容易踩的坑:SQLite 的外键约束名(CONSTRAINT fk_name)不是必须的,但缺失时,PRAGMA foreign_key_list 返回的 id 字段为 0,多个外键易混淆顺序。
跨数据库迁移时外键级联的兼容性雷区
MySQL 的 ON UPDATE CASCADE 在 PostgreSQL 中对应 ON UPDATE CASCADE,但 SQLite 不支持;PostgreSQL 的 ON DELETE RESTRICT 是默认行为,MySQL 却要显式写出来才生效。这些差异不会在导出时报警,只会在还原或执行时暴露。
真正危险的是隐式行为差异:
- MySQL 5.7+ 默认
STRICT_TRANS_TABLES,遇到外键冲突报错;而 PostgreSQL 默认是NO ACTION,可能延迟到事务提交时报错 - 某些 ORM(如 Django 的
dumpdata)默认只导模型数据,不导数据库级约束,级联逻辑全靠代码控制,备份文件里根本看不到ON DELETE - 如果用
mysqldump --no-create-info只导数据,那所有约束信息彻底消失,还原时哪怕表结构一模一样,也没法保证级联触发
最稳妥的做法:备份前先跑一遍 SELECT CONCAT('ALTER TABLE ', table_name, ' DROP FOREIGN KEY ', constraint_name, ';') FROM information_schema.key_column_usage WHERE referenced_table_name IS NOT NULL;,把当前外键定义存成快照,和 dump 文件一起归档——级联规则这种东西,宁可多存一份文本,别指望工具全给你兜住。










