Commit 2aa619ec authored by unknown's avatar unknown

MDEV-5788: Incorrect free of rgi->deferred_events in parallel replication

When an rpl_group_info object was returned from the free list, the
rgi->deferred_events_collecting and rgi->deferred_events was not correctly
re-inited. Additionally, the rgi->deferred_events was incorrectly freed in
free_rgi(), which causes unnecessary malloc/free (or crash when re-init is not
done).

Thanks to user nanyi607rao, who reported this bug on maria-developers@.
parent fe3c68b3
...@@ -706,6 +706,26 @@ SET GLOBAL binlog_format=@old_format; ...@@ -706,6 +706,26 @@ SET GLOBAL binlog_format=@old_format;
SET GLOBAL slave_parallel_threads=0; SET GLOBAL slave_parallel_threads=0;
SET GLOBAL slave_parallel_threads=10; SET GLOBAL slave_parallel_threads=10;
include/start_slave.inc include/start_slave.inc
*** MDEV-5788 Incorrect free of rgi->deferred_events in parallel replication ***
include/stop_slave.inc
SET GLOBAL replicate_ignore_table="test.t3";
SET GLOBAL slave_parallel_threads=2;
include/start_slave.inc
INSERT INTO t3 VALUES (100, rand());
INSERT INTO t3 VALUES (101, rand());
INSERT INTO t3 VALUES (102, rand());
INSERT INTO t3 VALUES (103, rand());
INSERT INTO t3 VALUES (104, rand());
INSERT INTO t3 VALUES (105, rand());
include/stop_slave.inc
SET GLOBAL replicate_ignore_table="";
include/start_slave.inc
INSERT INTO t3 VALUES (106, rand());
INSERT INTO t3 VALUES (107, rand());
SELECT * FROM t3 WHERE a >= 100 ORDER BY a;
a b
106 #
107 #
include/stop_slave.inc include/stop_slave.inc
SET GLOBAL slave_parallel_threads=@old_parallel_threads; SET GLOBAL slave_parallel_threads=@old_parallel_threads;
include/start_slave.inc include/start_slave.inc
......
...@@ -1069,6 +1069,47 @@ SET GLOBAL slave_parallel_threads=0; ...@@ -1069,6 +1069,47 @@ SET GLOBAL slave_parallel_threads=0;
SET GLOBAL slave_parallel_threads=10; SET GLOBAL slave_parallel_threads=10;
--source include/start_slave.inc --source include/start_slave.inc
--echo *** MDEV-5788 Incorrect free of rgi->deferred_events in parallel replication ***
--connection server_2
# Use just two worker threads, so we are sure to get the rpl_group_info added
# to the free list, which is what triggered the bug.
--source include/stop_slave.inc
SET GLOBAL replicate_ignore_table="test.t3";
SET GLOBAL slave_parallel_threads=2;
--source include/start_slave.inc
--connection server_1
INSERT INTO t3 VALUES (100, rand());
INSERT INTO t3 VALUES (101, rand());
--save_master_pos
--connection server_2
--sync_with_master
--connection server_1
INSERT INTO t3 VALUES (102, rand());
INSERT INTO t3 VALUES (103, rand());
INSERT INTO t3 VALUES (104, rand());
INSERT INTO t3 VALUES (105, rand());
--connection server_2
--sync_with_master
--source include/stop_slave.inc
SET GLOBAL replicate_ignore_table="";
--source include/start_slave.inc
--connection server_1
INSERT INTO t3 VALUES (106, rand());
INSERT INTO t3 VALUES (107, rand());
--save_master_pos
--connection server_2
--sync_with_master
--replace_column 2 #
SELECT * FROM t3 WHERE a >= 100 ORDER BY a;
--connection server_2 --connection server_2
--source include/stop_slave.inc --source include/stop_slave.inc
......
...@@ -789,9 +789,10 @@ rpl_parallel_thread::get_rgi(Relay_log_info *rli, Gtid_log_event *gtid_ev, ...@@ -789,9 +789,10 @@ rpl_parallel_thread::get_rgi(Relay_log_info *rli, Gtid_log_event *gtid_ev,
return NULL; return NULL;
} }
rgi->is_parallel_exec = true; rgi->is_parallel_exec = true;
if ((rgi->deferred_events_collecting= rli->mi->rpl_filter->is_on()))
rgi->deferred_events= new Deferred_log_events(rli);
} }
if ((rgi->deferred_events_collecting= rli->mi->rpl_filter->is_on()) &&
!rgi->deferred_events)
rgi->deferred_events= new Deferred_log_events(rli);
if (event_group_new_gtid(rgi, gtid_ev)) if (event_group_new_gtid(rgi, gtid_ev))
{ {
free_rgi(rgi); free_rgi(rgi);
...@@ -810,11 +811,6 @@ rpl_parallel_thread::free_rgi(rpl_group_info *rgi) ...@@ -810,11 +811,6 @@ rpl_parallel_thread::free_rgi(rpl_group_info *rgi)
mysql_mutex_assert_owner(&LOCK_rpl_thread); mysql_mutex_assert_owner(&LOCK_rpl_thread);
DBUG_ASSERT(rgi->commit_orderer.waitee == NULL); DBUG_ASSERT(rgi->commit_orderer.waitee == NULL);
rgi->free_annotate_event(); rgi->free_annotate_event();
if (rgi->deferred_events)
{
delete rgi->deferred_events;
rgi->deferred_events= NULL;
}
rgi->next= rgi_free_list; rgi->next= rgi_free_list;
rgi_free_list= rgi; rgi_free_list= rgi;
} }
......
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