首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL 主從複制中斷報錯「Cannot delete or update a parent row: a foreign key constraint fails」根因分析與 Bug 復現

     編輯:MySQL 綜合教學

MySQL 主從複制外鍵約束報錯深度排查:一個隱藏的 Bug

現象

從庫複制中斷,SHOW SLAVE STATUS\G 顯示:

Last_SQL_Error: Query caused different errors on master and slave.
Error on master: message (format)='Cannot delete or update a parent row: a foreign key constraint fails' error code=1217
Error on slave: actual message='no error', error code=0.
Query: 'DROP TABLE IF EXISTS `table1` /* generated by server */'

架構背景

  • 1 主 2 從,**選擇性複制**(replicate-do-db / replicate-ignore-db)。
  • 報錯的 SQL 發生在**未被複制的庫**(sas_basic)中,理論上不應出現在從庫 Relay Log。

排查與復現

  1. 檢查主庫 Binlog,確認 DROP TABLE IF EXISTS `table1` 確實在 sas_basic 執行。
  2. 懷疑主從表結構不一致 → 對比發現一致。
  3. 發現 MySQL 官方 Bug #77684:在使用 USE db 切換庫後執行 DROP TABLE,若從庫設有 replicate-do-db 或 replicate-ignore-db,會導致錯誤不同步,從庫報錯 1217 而主庫實際執行成功(或反之)。
  4. 測試環境完美復現:
    -- 主庫
    CREATE DATABASE db1;
    USE db1;
    CREATE TABLE table1 (ID BIGINT PRIMARY KEY) ENGINE=InnoDB;
    CREATE TABLE table2 (ID BIGINT AUTO_INCREMENT PRIMARY KEY, DIVISION_ID BIGINT,
        FOREIGN KEY (DIVISION_ID) REFERENCES table1(ID) ON DELETE CASCADE) ENGINE=InnoDB;
    DROP TABLE IF EXISTS table1;  -- 觸發 Bug
  5. 從庫設 replicate-do-db=test 或 replicate-ignore-db=test 均會觸發。

官方修復版本

承諾在 5.6.30 和 5.7.12 修復(生產環境 5.6.26 中招)。

規避方案

  • **避免在 USE db 上下文中跨庫操作 DDL**,改用全名 DROP TABLE IF EXISTS `db1`.`table1`;(但實測仍可能觸發,需升級版本徹底解決)。
  • 升級至修復版本(5.6.30+ / 5.7.12+)。
  • 若無法升級,監控從庫錯誤,遇此錯誤手動 SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; START SLAVE; 跳過(風險:可能導致數據不一致)。

總結

  1. 該 Bug 同時影響 replicate-do-db 和 replicate-ignore-db。
  2. 核心誘因:USE db + 外鍵關聯表 DROP TABLE + 選擇性複制規則。
  3. 生產環境建議:**盡量避免選擇性複制**,或升級版本;若必須用,嚴禁跨庫 DDL 操作。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved