Error 'Cannot add or update a child row: a foreign key constraint fails故障解決


一大早的,某從庫突然報出故障:SQL線程中斷

查看從庫狀態:

mysql> show slave status\G
 Slave_IO_State: Waiting for master to send event
  Master_Log_File: mysql-bin.026023
  Read_Master_Log_Pos: 230415889
  Relay_Log_File: relay-bin.058946
  Relay_Log_Pos: 54632056
  Relay_Master_Log_File: mysql-bin.026002
  Slave_IO_Running: Yes
  Slave_SQL_Running: No
  Last_Errno: 1452
  Last_Error: Error 'Cannot add or update a child row: a foreign key constraint fails (`zabbix`.`trigger_discovery`, CONSTRAINT `c_trigger_discovery_2` FOREIGN KEY (`parent_triggerid`) REFERENCES `triggers` (`triggerid`) ON DELETE CASCADE)' on query. Default database: 'zabbix'. Query: 'insert into trigger_discovery (triggerdiscoveryid,triggerid,parent_triggerid,name) values  (1677,26249,22532,'Free inodes is less than 20% on volume {#FSNAME}'), (1678,26250,22532,'Free inodes is less than 20% on volume {#FSNAME}'), (1679,26251,22532,'Free inodes is less than 20% on volume {#FSNAME}')'
  Exec_Master_Log_Pos: 54631910

重點關注報錯信息,定位問題,問題是:Cannot add or update a child row:a foreign key constraint fails ,涉及到的外鍵是:c_trigger_discovery_2

那這個外鍵的定義是什么呢?

報錯信息中也有列出:

trigger_discovery`, CONSTRAINT `c_trigger_discovery_2`  FOREIGN KEY (`parent_triggerid`) REFERENCES `triggers` (`triggerid`) ON DELETE CASCADE

那明白了,是表trigger_discovery中的列`parent_triggerid`和表triggers中的列`triggerid`有外鍵關聯,現在這里的數據插入出現了問題

那為什么會出現問題?

繼續看報錯,錯誤是從這里開始的:

insert into trigger_discovery (triggerdiscoveryid,triggerid,parent_triggerid,name) values  (1677,26249,22532,'Free inodes is less than 20% on volume {#FSNAME}')

上述外鍵對應的列parent_triggerid的值是22532,難道這個值在表triggers中有問題?

我們去表triggers中查看:

從庫
mysql> select * from triggers where triggerid=22532;
Empty set (0.00 sec)

主庫
mysql> select * from triggers where triggerid=22532;
+-----------+------------+--------------------------------------------------+-----+--------+-------+----------+------------+----------+-------+------------+------+-------------+-------+
| triggerid | expression | description                                      | url | status | value | priority | lastchange | comments | error | templateid | type | value_flags | flags |
+-----------+------------+--------------------------------------------------+-----+--------+-------+----------+------------+----------+-------+------------+------+-------------+-------+
|     22532 | {23251}<20 | Free inodes is less than 20% on volume {#FSNAME} |     |      0 |     0 |        2 |          0 |          |       |      13272 |    0 |           1 |     2 |
+-----------+------------+--------------------------------------------------+-----+--------+-------+----------+------------+----------+-------+------------+------+-------------+-------+
1 row in set (0.00 sec)

果然,從庫中沒有這個值對應的信息,但主庫中是有的,原來是主從不一致導致的,從庫中缺失這個值,主庫中順利插入了,但數據傳到從庫后,從庫的外鍵約束限制了這一插入操作,所以SQL線程阻塞。

問題找到了,那怎么解決?

首先,為了讓從庫盡快恢復運行,就先把這個錯誤跳過吧:

mysql>SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;        #跳過一個事務 
mysql>start slave;

接下來就是主從數據不一致的問題,可以使用pt-table-checksum來檢查下不一致的數據,再進行同步,具體步驟如下:

在主庫執行:

mysql>GRANT SELECT, PROCESS, SUPER, REPLICATION SLAVE,CREATE,DELETE,INSERT,UPDATE ON *.* TO 'USER'@'MASTER_HOST' identified  by 'PASSWORD';
注:創建用戶,這些權限都是必須的,否則會報錯

shell> ./pt-table-checksum --host='master_host' --user='user' --password='password' --port='port' --databases=zabbix --ignore-tables=ignore_table --recursion-method=processlist 
注:(1)因為涉及到的表太多,查看后發現很多表都有外鍵關聯,錯綜復雜,而且因為是監控表,即使丟失一些也沒什么關系,所以查出較大的且沒有外鍵關聯的表用ignore-tables選項排除,對其他表進行比對,如果表比較少的話直接指定--TABLES
    (2)recursion-method如果不設的話,會報錯:Diffs cannot be detected because no slaves were found.  其參數有四:processlist/hosts/dsn/no,用來決定查找slave的方式是show full processlist還是show slave hosts還是直接給出slave信息,具體用法在另一隨筆pt-table-checksum介紹中詳述

shell>./pt-table-sync --print --replicate=percona.checksums h=master_host,u=user,p=password,P=port h=slave_host,u=user,p=password,P=port --recursion-method=processlist >pt.log
注:最好使用--print,不要直接使用--execute,否則如果弄出問題,就更麻煩了,打印出直接執行的語句,去從庫執行就好了
將pt.log傳到從庫,直接執行,然后再次在主庫上進行一致性檢查,如果還有不一致的數據,記得登錄mysql去把checksums表清空,然后再次進行檢查同步,直到沒有不一致的數據。
當然,如果主從數據反復出現不一致的話,那就要先去檢查造成不一致的原因了,釜底抽薪才是硬道理。
 
       


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM