Commit 9856bb42 authored by Kristian Nielsen's avatar Kristian Nielsen

MDEV-31602: Race on rpl_global_gtid_slave_state when starting IO thread

Fix that rpl_slave_state::load() was calling rpl_slave_state::update() without
holding LOCK_slave_state.
Reviewed-by: default avatarMonty <monty@mariadb.org>
Signed-off-by: default avatarKristian Nielsen <knielsen@knielsen-hq.org>
parent 922db064
...@@ -45,9 +45,7 @@ rpl_slave_state::update_state_hash(uint64 sub_id, rpl_gtid *gtid, void *hton, ...@@ -45,9 +45,7 @@ rpl_slave_state::update_state_hash(uint64 sub_id, rpl_gtid *gtid, void *hton,
there will not be an attempt to delete the corresponding table row before there will not be an attempt to delete the corresponding table row before
it is even committed. it is even committed.
*/ */
mysql_mutex_lock(&LOCK_slave_state);
err= update(gtid->domain_id, gtid->server_id, sub_id, gtid->seq_no, hton, rgi); err= update(gtid->domain_id, gtid->server_id, sub_id, gtid->seq_no, hton, rgi);
mysql_mutex_unlock(&LOCK_slave_state);
if (err) if (err)
{ {
sql_print_warning("Slave: Out of memory during slave state maintenance. " sql_print_warning("Slave: Out of memory during slave state maintenance. "
...@@ -290,11 +288,24 @@ rpl_slave_state::truncate_hash() ...@@ -290,11 +288,24 @@ rpl_slave_state::truncate_hash()
int int
rpl_slave_state::update(uint32 domain_id, uint32 server_id, uint64 sub_id, rpl_slave_state::update(uint32 domain_id, uint32 server_id, uint64 sub_id,
uint64 seq_no, void *hton, rpl_group_info *rgi) uint64 seq_no, void *hton, rpl_group_info *rgi)
{
int res;
mysql_mutex_lock(&LOCK_slave_state);
res= update_nolock(domain_id, server_id, sub_id, seq_no, hton, rgi);
mysql_mutex_unlock(&LOCK_slave_state);
return res;
}
int
rpl_slave_state::update_nolock(uint32 domain_id, uint32 server_id, uint64 sub_id,
uint64 seq_no, void *hton, rpl_group_info *rgi)
{ {
element *elem= NULL; element *elem= NULL;
list_element *list_elem= NULL; list_element *list_elem= NULL;
DBUG_ASSERT(hton || !loaded); DBUG_ASSERT(hton || !loaded);
mysql_mutex_assert_owner(&LOCK_slave_state);
if (!(elem= get_element(domain_id))) if (!(elem= get_element(domain_id)))
return 1; return 1;
...@@ -308,7 +319,6 @@ rpl_slave_state::update(uint32 domain_id, uint32 server_id, uint64 sub_id, ...@@ -308,7 +319,6 @@ rpl_slave_state::update(uint32 domain_id, uint32 server_id, uint64 sub_id,
of all pending MASTER_GTID_WAIT(), so we do not slow down the of all pending MASTER_GTID_WAIT(), so we do not slow down the
replication SQL thread. replication SQL thread.
*/ */
mysql_mutex_assert_owner(&LOCK_slave_state);
elem->gtid_waiter= NULL; elem->gtid_waiter= NULL;
mysql_cond_broadcast(&elem->COND_wait_gtid); mysql_cond_broadcast(&elem->COND_wait_gtid);
} }
...@@ -1356,6 +1366,7 @@ rpl_slave_state::load(THD *thd, const char *state_from_master, size_t len, ...@@ -1356,6 +1366,7 @@ rpl_slave_state::load(THD *thd, const char *state_from_master, size_t len,
{ {
const char *end= state_from_master + len; const char *end= state_from_master + len;
mysql_mutex_assert_not_owner(&LOCK_slave_state);
if (reset) if (reset)
{ {
if (truncate_state_table(thd)) if (truncate_state_table(thd))
......
...@@ -231,6 +231,8 @@ struct rpl_slave_state ...@@ -231,6 +231,8 @@ struct rpl_slave_state
ulong count() const { return hash.records; } ulong count() const { return hash.records; }
int update(uint32 domain_id, uint32 server_id, uint64 sub_id, int update(uint32 domain_id, uint32 server_id, uint64 sub_id,
uint64 seq_no, void *hton, rpl_group_info *rgi); uint64 seq_no, void *hton, rpl_group_info *rgi);
int update_nolock(uint32 domain_id, uint32 server_id, uint64 sub_id,
uint64 seq_no, void *hton, rpl_group_info *rgi);
int truncate_state_table(THD *thd); int truncate_state_table(THD *thd);
void select_gtid_pos_table(THD *thd, LEX_CSTRING *out_tablename); void select_gtid_pos_table(THD *thd, LEX_CSTRING *out_tablename);
int record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id, int record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id,
......
...@@ -1927,7 +1927,7 @@ rpl_load_gtid_slave_state(THD *thd) ...@@ -1927,7 +1927,7 @@ rpl_load_gtid_slave_state(THD *thd)
for (i= 0; i < array.elements; ++i) for (i= 0; i < array.elements; ++i)
{ {
get_dynamic(&array, (uchar *)&tmp_entry, i); get_dynamic(&array, (uchar *)&tmp_entry, i);
if ((err= rpl_global_gtid_slave_state->update(tmp_entry.gtid.domain_id, if ((err= rpl_global_gtid_slave_state->update_nolock(tmp_entry.gtid.domain_id,
tmp_entry.gtid.server_id, tmp_entry.gtid.server_id,
tmp_entry.sub_id, tmp_entry.sub_id,
tmp_entry.gtid.seq_no, tmp_entry.gtid.seq_no,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment