Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions mysql-test/suite/galera/r/MDEV-34784.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
connection node_2;
connection node_1;
CREATE TABLE parent (
id INT PRIMARY KEY,
KEY (id)
) ENGINE=InnoDB;
CREATE TABLE child (
id INT PRIMARY KEY,
parent_id INT DEFAULT NULL,
FOREIGN KEY (parent_id)
REFERENCES parent(id)
) ENGINE=InnoDB;
connection node_2;
SET SESSION wsrep_sync_wait = 0;
SET GLOBAL wsrep_slave_threads=2;
SET GLOBAL DEBUG_DBUG = "d,sync.wsrep_apply_toi";
connection node_1;
ALTER TABLE parent ADD COLUMN (j INT);
connection node_2;
SET DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_toi_reached";
connection node_1;
INSERT INTO child(id) values (1);
connection node_2;
SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_toi";
SET SESSION wsrep_sync_wait = DEFAULT;
SET DEBUG_SYNC = "RESET";
SET GLOBAL DEBUG_DBUG = '';
SET GLOBAL wsrep_slave_threads = DEFAULT;
connection node_1;
DROP TABLE child;
DROP TABLE parent;
71 changes: 71 additions & 0 deletions mysql-test/suite/galera/t/MDEV-34784.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#
# Testing that foreign key constraint dependencies are correctly
# recorded in write set preventing harmfull parallel applying.
#
# In this scenario foreign reference column in child table is left
# NULL in a DML, and therefore the FK parent table is not appended
# in the key set. DDL execution on parent table will require table
# lock on FK child table
#

--source include/galera_cluster.inc
--source include/have_debug.inc
--source include/have_debug_sync.inc
--source include/galera_have_debug_sync.inc

CREATE TABLE parent (
id INT PRIMARY KEY,
KEY (id)
) ENGINE=InnoDB;

CREATE TABLE child (
id INT PRIMARY KEY,
parent_id INT DEFAULT NULL,
FOREIGN KEY (parent_id)
REFERENCES parent(id)
) ENGINE=InnoDB;


# Set up sync point for TOI applying in node 2
--connection node_2
SET SESSION wsrep_sync_wait = 0;
SET GLOBAL wsrep_slave_threads=2;

SET GLOBAL DEBUG_DBUG = "d,sync.wsrep_apply_toi";

# replicate ALTER
--connection node_1
ALTER TABLE parent ADD COLUMN (j INT);

# wait for ALTER to reach applying state
--connection node_2
SET DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_toi_reached";

#
# Expect the INSERT to depend on the ALTER,
# therefore it should wait for the ALTER to
# finish before it can be applied.
# If bug is present, the wait condition will
# timeout
#
--let $expected_apply_waits = `SELECT VARIABLE_VALUE+1 FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_apply_waits'`

--connection node_1
# note, the FK column will have NULL value
INSERT INTO child(id) values (1);

# check that the INSERT depends on ALTER and waits for ALTER to complete first
--connection node_2
--let $wait_condition = SELECT VARIABLE_VALUE = $expected_apply_waits FROM information_schema.global_status WHERE VARIABLE_NAME = 'wsrep_apply_waits'
--source include/wait_condition.inc
SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_toi";
SET SESSION wsrep_sync_wait = DEFAULT;

SET DEBUG_SYNC = "RESET";
SET GLOBAL DEBUG_DBUG = '';
SET GLOBAL wsrep_slave_threads = DEFAULT;

--connection node_1
DROP TABLE child;
DROP TABLE parent;

26 changes: 21 additions & 5 deletions sql/wsrep_mysqld.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1844,14 +1844,30 @@ bool wsrep_append_fk_parent_table(THD *thd, TABLE_LIST *tables,
FOREIGN_KEY_INFO *f_key_info;
List<FOREIGN_KEY_INFO> f_key_list;

table->table->file->get_foreign_key_list(thd, &f_key_list);
List_iterator_fast<FOREIGN_KEY_INFO> it(f_key_list);
while ((f_key_info= it++))
/* find FK parents */
{
WSREP_DEBUG("appended fkey %s", f_key_info->referenced_table->str);
keys->push_back(wsrep_prepare_key_for_toi(
table->table->file->get_foreign_key_list(thd, &f_key_list);
List_iterator_fast<FOREIGN_KEY_INFO> it(f_key_list);
while ((f_key_info= it++))
{
WSREP_DEBUG("appended parent FK key %s", f_key_info->referenced_table->str);
keys->push_back(wsrep_prepare_key_for_toi(
f_key_info->referenced_db->str, f_key_info->referenced_table->str,
wsrep::key::shared));
}
}

/* find FK children */
{
table->table->file->get_parent_foreign_key_list(thd, &f_key_list);
List_iterator_fast<FOREIGN_KEY_INFO> it(f_key_list);
while ((f_key_info= it++))
{
WSREP_DEBUG("appended child FK key %s", f_key_info->foreign_table->str);
keys->push_back(wsrep_prepare_key_for_toi(
f_key_info->foreign_db->str, f_key_info->foreign_table->str,
wsrep::key::shared));
}
}
Comment thread
sjaakola marked this conversation as resolved.
}
}
Expand Down
20 changes: 17 additions & 3 deletions storage/innobase/lock/lock0lock.cc
Original file line number Diff line number Diff line change
Expand Up @@ -567,7 +567,11 @@ static void wsrep_assert_valid_bf_bf_wait(const lock_t *lock, const trx_t *trx,
<< " index: "
<< lock->index->name()
<< " that has lock ";
lock_rec_print(stderr, lock, mtr);
if (!lock->is_table()) {
lock_rec_print(stderr, lock, mtr);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this safe i.e. is page always latched?

} else {
lock_table_print(stderr, lock);
}

ib::error() << "WSREP state: ";

Expand Down Expand Up @@ -1068,10 +1072,20 @@ void wsrep_report_error(const lock_t* victim_lock, const trx_t *bf_trx)
// should not execute concurrently
mtr_t mtr;
WSREP_ERROR("BF request is not compatible with victim");

auto print_lock_details = [&](const lock_t* lock) {
if (!lock->is_table()) {
lock_rec_print(stderr, lock, mtr);
} else {
lock_table_print(stderr, lock);
}
};

WSREP_ERROR("BF requesting lock: ");
lock_rec_print(stderr, bf_trx->lock.wait_lock, mtr);
print_lock_details(bf_trx->lock.wait_lock);

WSREP_ERROR("victim holding lock: ");
lock_rec_print(stderr, victim_lock, mtr);
print_lock_details(victim_lock);
}
#endif /* WITH_DEBUG */

Expand Down