首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 還原報錯 1005 errno 121 根因與解決:外鍵名稱衝突、ibdata1 污染、乾淨重建

     編輯:MySQL 資料庫相關知識

還原 SQL 文件報錯 ERROR 1005 (HY000): Can't create table ... (errno: 121),核心原因是 **外鍵約束名稱在實例內必須唯一**,或系統表空間 ibdata1 被舊備份污染導致元數據衝突。

錯誤碼解析

  • 1005:無法創建表
  • errno: 121:外鍵名稱重複(MySQL 內部錯誤碼映射)
  • 等價於:ERROR 1005: Can't create table 'xxx' (errno: 121 "Duplicate key on write or update")

兩大典型場景

場景一:外鍵名稱衝突(最常見)

MySQL 要求 **外鍵名稱(constraint symbol)在全實例唯一**,不僅在表內。若兩張表定義了同名外鍵(如均為 fk_user_id),第二張表創建失敗。


-- 表 A
CONSTRAINT `fk_user_id` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`)

-- 表 B(同庫/不同庫)
CONSTRAINT `fk_user_id` FOREIGN KEY (`user_id`) REFERENCES `users`(`id`)
-- 報錯 1005 errno 121

解決:外鍵命名加表前綴 fk_orders_user_id、fk_logs_user_id,或不顯式命名讓 MySQL 自動生成唯一名。

場景二:ibdata1 系統表空間污染(隱蔽且嚴重)

操作:新裝 MySQL → 用舊實例 ibdata1 覆蓋新 ibdata1 → 嘗試導入 SQL 還原數據 → 報錯 1005/其他元數據錯誤。

原因:ibdata1 存儲數據字典、Undo Log、雙寫緩衝、外鍵元數據。舊 ibdata1 含舊表定義、外鍵名稱,與新導入 SQL 定義衝突。

解決**:

  1. 停止 MySQL
  2. 刪除/備份被污染的 ibdata1、ib_logfile*
  3. 啟動 MySQL(自動生成乾淨 ibdata1)
  4. 重新導入 SQL 文件

通用排查清單

檢查點命令/動作
外鍵名稱唯一性SELECT CONSTRAINT_NAME, TABLE_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_TYPE='FOREIGN KEY' GROUP BY CONSTRAINT_NAME HAVING COUNT(*)>1;
SQL 文件中是否重複定義同名外鍵grep -n "CONSTRAINT.*FOREIGN KEY" backup.sql | sort | uniq -d
ibdata1 是否為舊備份覆蓋對比文件修改時間、大小;新實例應為自動生成的小文件(~12MB)
目標庫是否殘留舊表DROP DATABASE IF EXISTS target_db; CREATE DATABASE target_db; 乾淨重建
字符集/排序規則一致庫表 CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

最佳實踐:還原前「三乾淨」

  1. 乾淨庫:DROP DATABASE ...; CREATE DATABASE ... CHARSET=utf8mb4;
  2. 乾淨 ibdata1:勿手動替換系統表空間,讓 MySQL 自管理
  3. 乾淨外鍵命名:規範 fk_子表_父表_欄位,全局唯一

「乾淨重建」比「排查修補」快十倍,錯誤 1005/121 九成源於「髒環境」。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved