Skip to content

Commit ef2dbb8

Browse files
sjaakolasanja-byelkin
authored andcommitted
MDEV-23328 Server hang due to Galera lock conflict resolution
Mutex order violation when wsrep bf thread kills a conflicting trx, the stack is wsrep_thd_LOCK() wsrep_kill_victim() lock_rec_other_has_conflicting() lock_clust_rec_read_check_and_lock() row_search_mvcc() ha_innobase::index_read() ha_innobase::rnd_pos() handler::ha_rnd_pos() handler::rnd_pos_by_record() handler::ha_rnd_pos_by_record() Rows_log_event::find_row() Update_rows_log_event::do_exec_row() Rows_log_event::do_apply_event() Log_event::apply_event() wsrep_apply_events() and mutexes are taken in the order lock_sys->mutex -> victim_trx->mutex -> victim_thread->LOCK_thd_data When a normal KILL statement is executed, the stack is innobase_kill_query() kill_handlerton() plugin_foreach_with_mask() ha_kill_query() THD::awake() kill_one_thread() and mutexes are victim_thread->LOCK_thd_data -> lock_sys->mutex -> victim_trx->mutex This patch is the plan D variant for fixing potetial mutex locking order exercised by BF aborting and KILL command execution. In this approach, KILL command is replicated as TOI operation. This guarantees total isolation for the KILL command execution in the first node: there is no concurrent replication applying and no concurrent DDL executing. Therefore there is no risk of BF aborting to happen in parallel with KILL command execution either. Potential mutex deadlocks between the different mutex access paths with KILL command execution and BF aborting cannot therefore happen. TOI replication is used, in this approach, purely as means to provide isolated KILL command execution in the first node. KILL command should not (and must not) be applied in secondary nodes. In this patch, we make this sure by skipping KILL execution in secondary nodes, in applying phase, where we bail out if applier thread is trying to execute KILL command. This is effective, but skipping the applying of KILL command could happen much earlier as well. This also fixed unprotected calls to wsrep_thd_abort that will use wsrep_abort_transaction. This is fixed by holding THD::LOCK_thd_data while we abort transaction. Reviewed-by: Jan Lindström <jan.lindstrom@mariadb.com>
1 parent d5bc057 commit ef2dbb8

21 files changed

+317
-409
lines changed

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

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ f1 f2 f3
6868
10 10 0
6969
INSERT INTO t1 VALUES (7,7,7);
7070
INSERT INTO t1 VALUES (8,8,8);
71-
DROP TABLE t1;
72-
test scenario 2
73-
connection node_1;
71+
SELECT COUNT(*) FROM t1;
72+
COUNT(*)
73+
7
7474
CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 int, f3 int, unique key keyj (f2));
7575
INSERT INTO t1 VALUES (1, 1, 0);
7676
INSERT INTO t1 VALUES (3, 3, 0);
@@ -92,9 +92,9 @@ SET SESSION wsrep_on = 1;
9292
SET GLOBAL wsrep_provider_options = 'dbug=';
9393
SET GLOBAL wsrep_provider_options = 'dbug=d,commit_monitor_master_enter_sync';
9494
connection node_1;
95-
COMMIT;
96-
connection node_1a;
97-
SET SESSION wsrep_on = 0;
95+
SELECT COUNT(*) FROM t1;
96+
COUNT(*)
97+
7
9898
SET SESSION wsrep_on = 1;
9999
SET GLOBAL wsrep_provider_options = 'dbug=';
100100
SET GLOBAL DEBUG_DBUG = "d,sync.wsrep_replay_cb";
@@ -125,6 +125,7 @@ f1 f2 f3
125125
3 3 1
126126
4 4 2
127127
5 5 2
128+
8 8 8
128129
10 10 0
129130
INSERT INTO t1 VALUES (7,7,7);
130131
INSERT INTO t1 VALUES (8,8,8);

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

Lines changed: 0 additions & 54 deletions
This file was deleted.

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

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,22 +23,6 @@ connection node_1a;
2323
connection node_1b;
2424
connection node_2;
2525
connection node_2a;
26-
connection node_1;
27-
SET SESSION wsrep_sync_wait=15;
28-
SELECT COUNT(*) FROM parent;
29-
COUNT(*)
30-
20001
31-
SELECT COUNT(*) FROM child;
32-
COUNT(*)
33-
10000
34-
connection node_2;
35-
SET SESSION wsrep_sync_wait=15;
36-
SELECT COUNT(*) FROM parent;
37-
COUNT(*)
38-
20001
39-
SELECT COUNT(*) FROM child;
40-
COUNT(*)
41-
10000
4226
DROP TABLE child;
4327
DROP TABLE parent;
4428
DROP TABLE ten;

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

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,14 @@ SELECT * FROM t1;
140140
# original state in node 1
141141
INSERT INTO t1 VALUES (7,7,7);
142142
INSERT INTO t1 VALUES (8,8,8);
143+
SELECT COUNT(*) FROM t1;
144+
SELECT * FROM t1;
145+
146+
--connection node_1
147+
--let $wait_condition = SELECT COUNT(*) = 7 FROM t1
148+
--source include/wait_condition.inc
149+
SELECT COUNT(*) FROM t1;
150+
SELECT * FROM t1;
143151

144152
DROP TABLE t1;
145153

@@ -199,9 +207,9 @@ INSERT INTO t1 VALUES (5, 5, 2);
199207
--source include/galera_set_sync_point.inc
200208

201209
--connection node_1
202-
--send COMMIT
203-
204-
--connection node_1a
210+
--let $wait_condition = SELECT COUNT(*) = 7 FROM t1
211+
--source include/wait_condition.inc
212+
SELECT COUNT(*) FROM t1;
205213
# wait for the local commit to enter in commit monitor wait state
206214
--let $galera_sync_point = apply_monitor_slave_enter_sync commit_monitor_master_enter_sync
207215
--source include/galera_wait_sync_point.inc
@@ -273,4 +281,13 @@ SELECT * FROM t1;
273281
INSERT INTO t1 VALUES (7,7,7);
274282
INSERT INTO t1 VALUES (8,8,8);
275283

284+
SELECT COUNT(*) FROM t1;
285+
SELECT * FROM t1;
286+
287+
--connection node_1
288+
--let $wait_condition = SELECT COUNT(*) = 7 FROM t1
289+
--source include/wait_condition.inc
290+
SELECT COUNT(*) FROM t1;
291+
SELECT * FROM t1;
292+
276293
DROP TABLE t1;

mysql-test/suite/galera/t/galera_bf_kill_debug.cnf

Lines changed: 0 additions & 7 deletions
This file was deleted.

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

Lines changed: 0 additions & 140 deletions
This file was deleted.

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

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,11 @@ INSERT INTO parent VALUES (1, 0);
5454
--connection node_2a
5555
--reap
5656

57-
--connection node_1
58-
SET SESSION wsrep_sync_wait=15;
59-
SELECT COUNT(*) FROM parent;
60-
SELECT COUNT(*) FROM child;
61-
62-
--connection node_2
63-
SET SESSION wsrep_sync_wait=15;
64-
SELECT COUNT(*) FROM parent;
65-
SELECT COUNT(*) FROM child;
57+
#
58+
# ALTER TABLE could bf kill one or more of INSERTs to parent, so
59+
# the actual number of rows in PARENT depends on whether
60+
# the INSERT is committed before ALTER TABLE is executed
61+
#
6662

6763
DROP TABLE child;
6864
DROP TABLE parent;

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,13 @@ SELECT * FROM t1;
9494
--eval SET GLOBAL wsrep_auto_increment_control = $auto_increment_control_orig
9595
--eval SET GLOBAL auto_increment_increment = $auto_increment_increment_node1
9696
--eval SET GLOBAL auto_increment_offset = $auto_increment_offset_node1
97+
--disconnect node_1a
9798

9899
--connection node_2
99100
--eval SET GLOBAL wsrep_auto_increment_control = $auto_increment_control_orig
100101
--eval SET GLOBAL auto_increment_increment = $auto_increment_increment_node2
101102
--eval SET GLOBAL auto_increment_offset = $auto_increment_offset_node2
103+
--disconnect node_2a
102104

103105
--enable_query_log
104106

sql/handler.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -913,7 +913,7 @@ static my_bool kill_handlerton(THD *thd, plugin_ref plugin,
913913
{
914914
handlerton *hton= plugin_hton(plugin);
915915

916-
mysql_mutex_assert_owner(&thd->LOCK_thd_data);
916+
mysql_mutex_assert_owner(&thd->LOCK_thd_kill);
917917
if (hton->kill_query && thd_get_ha_data(thd, hton))
918918
hton->kill_query(hton, thd, *(enum thd_kill_levels *) level);
919919
return FALSE;

0 commit comments

Comments
 (0)