Skip to content

Commit 22e5686

Browse files
committed
MDEV-36923 : Add warning messages for applier FK failures
Add warning messages if applier write set execution fails because of foreign key constraint error. Warnings are printed by default and can be disabled using SET GLOBAL wsrep_mode=APPLIER_DISABLE_FK_WARNINGS.
1 parent 8be6d25 commit 22e5686

19 files changed

+369
-22
lines changed

include/mysql/service_wsrep.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ enum Wsrep_service_key_type
1414
#else
1515

1616
/* Copyright (c) 2015, 2020, MariaDB Corporation Ab
17-
2018 Codership Oy <[email protected]>
17+
2018, 2025, Codership Oy <[email protected]>
1818
1919
This program is free software; you can redistribute it and/or modify
2020
it under the terms of the GNU General Public License as published by
@@ -96,6 +96,7 @@ extern struct wsrep_service_st {
9696
void (*wsrep_thd_kill_UNLOCK_func)(const MYSQL_THD thd);
9797
void (*wsrep_thd_set_wsrep_PA_unsafe_func)(MYSQL_THD thd);
9898
uint32 (*wsrep_get_domain_id_func)();
99+
my_bool (*wsrep_applier_log_warnings)(const MYSQL_THD thd);
99100
} *wsrep_service;
100101

101102
#define MYSQL_SERVICE_WSREP_INCLUDED
@@ -146,6 +147,7 @@ extern struct wsrep_service_st {
146147
#define wsrep_report_bf_lock_wait(T,I) wsrep_service->wsrep_report_bf_lock_wait(T,I)
147148
#define wsrep_thd_set_PA_unsafe(T) wsrep_service->wsrep_thd_set_PA_unsafe_func(T)
148149
#define wsrep_get_domain_id(T) wsrep_service->wsrep_get_domain_id_func(T)
150+
#define wsrep_applier_log_warnings(T) wsrep_service->wsrep_applier_log_warnings_func(T)
149151
#else
150152

151153
#define MYSQL_SERVICE_WSREP_STATIC_INCLUDED
@@ -256,5 +258,6 @@ extern "C" void wsrep_report_bf_lock_wait(const THD *thd,
256258
/* declare parallel applying unsafety for the THD */
257259
extern "C" void wsrep_thd_set_PA_unsafe(MYSQL_THD thd);
258260
extern "C" uint32 wsrep_get_domain_id();
261+
extern "C" my_bool wsrep_applier_log_warnings(const MYSQL_THD thd);
259262
#endif
260263
#endif /* MYSQL_SERVICE_WSREP_INCLUDED */
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
connection node_2;
2+
connection node_1;
3+
CREATE TABLE parent (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
4+
CREATE TABLE child (f1 INTEGER PRIMARY KEY, p_id INTEGER,
5+
f2 INTEGER,
6+
CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES parent (f1) ON DELETE CASCADE) ;
7+
CREATE TABLE grandchild (f1 INTEGER PRIMARY KEY, p_id INTEGER,
8+
f2 INTEGER,
9+
CONSTRAINT fk_2 FOREIGN KEY (p_id) REFERENCES child (p_id)) ;
10+
INSERT INTO parent VALUES (1, 1),(2,2);
11+
INSERT INTO child VALUES (1, 1, 1);
12+
connection node_1;
13+
# Make node 1 tolerate split-brain
14+
SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true';
15+
SET GLOBAL wsrep_provider_options = 'pc.weight=2';
16+
connection node_2;
17+
SET SESSION wsrep_on=OFF;
18+
DELETE FROM child WHERE f1 = 1;
19+
connection node_1;
20+
# Fails in node_2 with Foreign key warning in table: `test`.`grandchild` constraint `fk_2` failed err: adding an index entry to a child table failed.
21+
INSERT INTO grandchild VALUES (1,1,1);
22+
# Restart node_2, force SST. This is needed as node_2 is on inconsistent state
23+
connection node_2;
24+
connection node_1;
25+
connection node_2;
26+
Starting server ...
27+
include/assert_grep.inc [Foreign key warning in table]
28+
include/assert_grep.inc [adding an index entry to a child table failed]
29+
connection node_1;
30+
drop table grandchild;
31+
drop table child;
32+
drop table parent;
33+
SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=false';
34+
SET GLOBAL wsrep_provider_options = 'pc.weight=1';
35+
connection node_2;
36+
call mtr.add_suppression("WSREP: Foreign key warning in table");
37+
call mtr.add_suppression("WSREP: Event 3 Write_rows_v1 apply failed");
38+
call mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on");
39+
call mtr.add_suppression("WSREP: Failed to apply write set");

mysql-test/suite/galera/r/MW-369.result

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,9 @@ SET SESSION DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb';
258258
SET GLOBAL DEBUG_DBUG = "";
259259
SET DEBUG_SYNC = 'RESET';
260260
connection node_1;
261+
# Now there should be 1 WSREP Foreign key constraint warning
262+
include/assert_grep.inc [Foreign key warning in table]
263+
include/assert_grep.inc [Setting shared record lock to matching record in the child table failed]
261264
connection node_2;
262265
SELECT * FROM pg;
263266
f1 f2
@@ -268,3 +271,45 @@ f1 p_id f2
268271
1 1 0
269272
DROP TABLE cg;
270273
DROP TABLE pg;
274+
connection node_1;
275+
CREATE TABLE `pg-` (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
276+
CREATE TABLE `cg-` (f1 INTEGER PRIMARY KEY, p_id INTEGER,
277+
f2 INTEGER,
278+
CONSTRAINT `fk_1-$$` FOREIGN KEY (p_id) REFERENCES `pg-` (f1)) ;
279+
INSERT INTO `pg-` VALUES (1, 0);
280+
INSERT INTO `pg-` VALUES (2, 0);
281+
connection node_1;
282+
SET AUTOCOMMIT=ON;
283+
START TRANSACTION;
284+
UPDATE `pg-` SET f2 = 1 WHERE f1 = 1;
285+
connection node_1a;
286+
SET SESSION wsrep_sync_wait = 0;
287+
SET GLOBAL DEBUG_DBUG = "d,sync.wsrep_apply_cb";
288+
connection node_2;
289+
INSERT INTO `cg-` VALUES (1, 1, 0);
290+
connection node_1a;
291+
SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached";
292+
connection node_1;
293+
SET SESSION DEBUG_SYNC = "wsrep_before_certification SIGNAL before_certification_reached WAIT_FOR continue_before_certification";
294+
COMMIT;
295+
connection node_1a;
296+
SET SESSION DEBUG_SYNC = "now WAIT_FOR before_certification_reached";
297+
SET SESSION DEBUG_SYNC = 'now SIGNAL continue_before_certification';
298+
SET SESSION DEBUG_SYNC = 'now SIGNAL signal.wsrep_apply_cb';
299+
SET GLOBAL DEBUG_DBUG = "";
300+
SET DEBUG_SYNC = 'RESET';
301+
connection node_1;
302+
call mtr.add_suppression("WSREP: Foreign key warning");
303+
# Now there should be 2 WSREP Foreign key constraint warnings
304+
include/assert_grep.inc [Foreign key warning in table]
305+
include/assert_grep.inc [Setting shared record lock to matching record in the child table failed]
306+
connection node_2;
307+
SELECT * FROM `pg-`;
308+
f1 f2
309+
1 1
310+
2 0
311+
SELECT * FROM `cg-`;
312+
f1 p_id f2
313+
1 1 0
314+
DROP TABLE `cg-`;
315+
DROP TABLE `pg-`;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
--- galera_FK_duplicate_client_insert.result
2+
+++ galera_FK_duplicate_client_insert.reject
3+
@@ -380,6 +380,4 @@
4+
set debug_sync = reset;
5+
connection node_1;
6+
drop table user_session,user;
7+
-# Now there should be 10 WSREP Foreign key constraint warnings
8+
-include/assert_grep.inc [Foreign key warning in table]
9+
call mtr.add_suppression("WSREP: Foreign key warning in table");

mysql-test/suite/galera/r/galera_FK_duplicate_client_insert.result

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,3 +380,6 @@ truncate user_session;
380380
set debug_sync = reset;
381381
connection node_1;
382382
drop table user_session,user;
383+
# Now there should be 10 WSREP Foreign key constraint warnings
384+
include/assert_grep.inc [Foreign key warning in table]
385+
call mtr.add_suppression("WSREP: Foreign key warning in table");

mysql-test/suite/galera/r/galera_var_wsrep_mode.result

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ SET GLOBAL wsrep_mode='A';
2020
ERROR 42000: Variable 'wsrep_mode' can't be set to the value of 'A'
2121
SET GLOBAL wsrep_mode=NULL;
2222
ERROR 42000: Variable 'wsrep_mode' can't be set to the value of 'NULL'
23-
SET GLOBAL wsrep_mode=128;
24-
ERROR 42000: Variable 'wsrep_mode' can't be set to the value of '128'
23+
SET GLOBAL wsrep_mode=65536;
24+
ERROR 42000: Variable 'wsrep_mode' can't be set to the value of '65536'
2525
SET GLOBAL wsrep_mode=REQUIRED_PRIMARY_KEY,REPLICATE_MYISAM;
2626
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1
2727
SET GLOBAL wsrep_mode=1;
@@ -56,6 +56,10 @@ SET GLOBAL wsrep_mode=REPLICATE_ARIA;
5656
SELECT @@wsrep_mode;
5757
@@wsrep_mode
5858
REPLICATE_ARIA
59+
SET GLOBAL wsrep_mode=APPLIER_DISABLE_FK_WARNINGS;
60+
SELECT @@wsrep_mode;
61+
@@wsrep_mode
62+
APPLIER_DISABLE_FK_WARNINGS
5963
SET GLOBAL wsrep_mode=DISALLOW_LOCAL_GTID;
6064
SELECT @@wsrep_mode;
6165
@@wsrep_mode
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
--source include/galera_cluster.inc
2+
3+
#
4+
# Delete parent row that is needed for insert to child
5+
#
6+
CREATE TABLE parent (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
7+
CREATE TABLE child (f1 INTEGER PRIMARY KEY, p_id INTEGER,
8+
f2 INTEGER,
9+
CONSTRAINT fk_1 FOREIGN KEY (p_id) REFERENCES parent (f1) ON DELETE CASCADE) ;
10+
CREATE TABLE grandchild (f1 INTEGER PRIMARY KEY, p_id INTEGER,
11+
f2 INTEGER,
12+
CONSTRAINT fk_2 FOREIGN KEY (p_id) REFERENCES child (p_id)) ;
13+
14+
15+
INSERT INTO parent VALUES (1, 1),(2,2);
16+
INSERT INTO child VALUES (1, 1, 1);
17+
18+
--connection node_1
19+
--echo # Make node 1 tolerate split-brain
20+
SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=true';
21+
SET GLOBAL wsrep_provider_options = 'pc.weight=2';
22+
23+
--connection node_2
24+
--let $wait_condition = SELECT COUNT(*) = 1 FROM child;
25+
--source include/wait_condition.inc
26+
27+
SET SESSION wsrep_on=OFF;
28+
DELETE FROM child WHERE f1 = 1;
29+
30+
--connection node_1
31+
--echo # Fails in node_2 with Foreign key warning in table: `test`.`grandchild` constraint `fk_2` failed err: adding an index entry to a child table failed.
32+
INSERT INTO grandchild VALUES (1,1,1);
33+
34+
--echo # Restart node_2, force SST. This is needed as node_2 is on inconsistent state
35+
--connection node_2
36+
--source include/shutdown_mysqld.inc
37+
--remove_file $MYSQLTEST_VARDIR/mysqld.2/data/grastate.dat
38+
39+
--connection node_1
40+
--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'
41+
--source include/wait_condition.inc
42+
43+
--connection node_2
44+
--echo Starting server ...
45+
let $restart_noprint=2;
46+
--source include/start_mysqld.inc
47+
48+
--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
49+
--source include/wait_condition.inc
50+
51+
--let $assert_count = 1
52+
--let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.2.err
53+
--let $assert_text = Foreign key warning in table
54+
--let $assert_select = Foreign key warning in table
55+
--source include/assert_grep.inc
56+
--let $assert_text = adding an index entry to a child table failed
57+
--let $assert_select = adding an index entry to a child table failed
58+
--source include/assert_grep.inc
59+
60+
--connection node_1
61+
drop table grandchild;
62+
drop table child;
63+
drop table parent;
64+
# restore provider options
65+
SET GLOBAL wsrep_provider_options = 'pc.ignore_sb=false';
66+
SET GLOBAL wsrep_provider_options = 'pc.weight=1';
67+
68+
--connection node_2
69+
call mtr.add_suppression("WSREP: Foreign key warning in table");
70+
# These are required because test intentionally causes inconsistency
71+
call mtr.add_suppression("WSREP: Event 3 Write_rows_v1 apply failed");
72+
call mtr.add_suppression("WSREP: Inconsistency detected: Inconsistent by consensus on");
73+
call mtr.add_suppression("WSREP: Failed to apply write set");

mysql-test/suite/galera/t/MW-369.test

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
#
2323

2424
--source include/galera_cluster.inc
25-
--source include/have_innodb.inc
25+
--source include/have_debug.inc
2626
--source include/have_debug_sync.inc
2727

2828
CREATE TABLE p (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
@@ -334,9 +334,54 @@ INSERT INTO pg VALUES (2, 0);
334334
--connection node_1
335335
--reap
336336

337+
--echo # Now there should be 1 WSREP Foreign key constraint warning
338+
--let $assert_count = 1
339+
--let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.1.err
340+
--let $assert_text = Foreign key warning in table
341+
--let $assert_select = Foreign key warning in table
342+
--source include/assert_grep.inc
343+
--let $assert_text = Setting shared record lock to matching record in the child table failed
344+
--let $assert_select = Setting shared record lock to matching record in the child table failed
345+
--source include/assert_grep.inc
346+
337347
--connection node_2
338348
SELECT * FROM pg;
339349
SELECT * FROM cg;
340350

341351
DROP TABLE cg;
342352
DROP TABLE pg;
353+
354+
--connection node_1
355+
CREATE TABLE `pg-` (f1 INTEGER PRIMARY KEY, f2 INTEGER) ENGINE=INNODB;
356+
CREATE TABLE `cg-` (f1 INTEGER PRIMARY KEY, p_id INTEGER,
357+
f2 INTEGER,
358+
CONSTRAINT `fk_1-$$` FOREIGN KEY (p_id) REFERENCES `pg-` (f1)) ;
359+
360+
INSERT INTO `pg-` VALUES (1, 0);
361+
INSERT INTO `pg-` VALUES (2, 0);
362+
363+
--let mw_369_parent_query = UPDATE `pg-` SET f2 = 1 WHERE f1 = 1
364+
--let $mw_369_child_query = INSERT INTO `cg-` VALUES (1, 1, 0)
365+
--source MW-369.inc
366+
367+
# Commit succeeds
368+
--connection node_1
369+
--reap
370+
call mtr.add_suppression("WSREP: Foreign key warning");
371+
372+
--echo # Now there should be 2 WSREP Foreign key constraint warnings
373+
--let $assert_count = 2
374+
--let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.1.err
375+
--let $assert_text = Foreign key warning in table
376+
--let $assert_select = Foreign key warning in table
377+
--source include/assert_grep.inc
378+
--let $assert_text = Setting shared record lock to matching record in the child table failed
379+
--let $assert_select = Setting shared record lock to matching record in the child table failed
380+
--source include/assert_grep.inc
381+
382+
--connection node_2
383+
SELECT * FROM `pg-`;
384+
SELECT * FROM `cg-`;
385+
386+
DROP TABLE `cg-`;
387+
DROP TABLE `pg-`;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[no_warnings]
2+
wsrep-mode=APPLIER_DISABLE_FK_WARNINGS
3+
4+
[warnings]
5+
wsrep-mode=0

mysql-test/suite/galera/t/galera_FK_duplicate_client_insert.test

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,3 +159,17 @@ while($counter > 0)
159159
--connection node_1
160160

161161
drop table user_session,user;
162+
163+
let $wsrep_mode = `SELECT @@GLOBAL.wsrep_mode`;
164+
165+
if ($wsrep_mode != APPLIER_DISABLE_FK_WARNINGS)
166+
{
167+
--echo # Now there should be 10 WSREP Foreign key constraint warnings
168+
--let $assert_count = 10
169+
--let $assert_file = $MYSQLTEST_VARDIR/log/mysqld.1.err
170+
--let $assert_text = Foreign key warning in table
171+
--let $assert_select = Foreign key warning in table
172+
--source include/assert_grep.inc
173+
}
174+
175+
call mtr.add_suppression("WSREP: Foreign key warning in table");

0 commit comments

Comments
 (0)