mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-6775: Wrong binlog order in parallel replication: Intermediate commit
The code in binlog group commit around wait_for_commit that controls commit order, did the wakeup of subsequent commits early, as soon as a following transaction is put into the group commit queue, but before any such commit has actually taken place. This causes problems with too early wakeup of transactions that need to wait for prior to commit, but do not take part in the binlog group commit for one reason or the other. This patch solves the problem, by moving the wakeup to happen only after the binlog group commit is completed. This requires a new solution to ensure that transactions that arrive later than the leader are still able to participate in group commit. This patch introduces a flag wait_for_commit::commit_started. When this is set, a waiter can queue up itself in the group commit queue. This way, effectively the wait_for_prior_commit() is skipped only for transactions that participate in group commit, so that skipping the wait is safe. Other transactions still wait as needed for correctness.
This commit is contained in:
@ -1466,6 +1466,75 @@ SET sql_slave_skip_counter= 1;
|
||||
SELECT * FROM t2 WHERE a >= 30 ORDER BY a;
|
||||
|
||||
|
||||
--echo *** MDEV-6775: Wrong binlog order in parallel replication ***
|
||||
--connection server_1
|
||||
# A bit tricky bug to reproduce. On the master, we binlog in statement-mode
|
||||
# two transactions, an UPDATE followed by a DELETE. On the slave, we replicate
|
||||
# with binlog-mode set to ROW, which means the DELETE, which modifies no rows,
|
||||
# is not binlogged. Then we inject a wait in the group commit code on the
|
||||
# slave, shortly before the actual commit of the UPDATE. The bug was that the
|
||||
# DELETE could wake up from wait_for_prior_commit() before the commit of the
|
||||
# UPDATE. So the test could see the slave position updated to after DELETE,
|
||||
# while the UPDATE was still not visible.
|
||||
DELETE FROM t4;
|
||||
INSERT INTO t4 VALUES (1,NULL), (3,NULL), (4,4), (5, NULL), (6, 6);
|
||||
--source include/save_master_gtid.inc
|
||||
|
||||
--connection server_2
|
||||
--source include/sync_with_master_gtid.inc
|
||||
--source include/stop_slave.inc
|
||||
SET @old_dbug= @@GLOBAL.debug_dbug;
|
||||
SET GLOBAL debug_dbug="+d,inject_binlog_commit_before_get_LOCK_log";
|
||||
SET @old_format=@@GLOBAL.binlog_format;
|
||||
SET GLOBAL binlog_format=ROW;
|
||||
# Re-spawn the worker threads to be sure they pick up the new binlog format
|
||||
SET GLOBAL slave_parallel_threads=0;
|
||||
SET GLOBAL slave_parallel_threads=10;
|
||||
|
||||
--connection con1
|
||||
SET @old_format= @@binlog_format;
|
||||
SET binlog_format= statement;
|
||||
SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
|
||||
send UPDATE t4 SET b=NULL WHERE a=6;
|
||||
--connection server_1
|
||||
SET debug_sync='now WAIT_FOR master_queued1';
|
||||
|
||||
--connection con2
|
||||
SET @old_format= @@binlog_format;
|
||||
SET binlog_format= statement;
|
||||
SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
|
||||
send DELETE FROM t4 WHERE b <= 3;
|
||||
|
||||
--connection server_1
|
||||
SET debug_sync='now WAIT_FOR master_queued2';
|
||||
SET debug_sync='now SIGNAL master_cont1';
|
||||
|
||||
--connection con1
|
||||
REAP;
|
||||
SET binlog_format= @old_format;
|
||||
--connection con2
|
||||
REAP;
|
||||
SET binlog_format= @old_format;
|
||||
SET debug_sync='RESET';
|
||||
--save_master_pos
|
||||
SELECT * FROM t4 ORDER BY a;
|
||||
|
||||
--connection server_2
|
||||
--source include/start_slave.inc
|
||||
SET debug_sync= 'now WAIT_FOR waiting';
|
||||
--sync_with_master
|
||||
SELECT * FROM t4 ORDER BY a;
|
||||
SET debug_sync= 'now SIGNAL cont';
|
||||
|
||||
# Re-spawn the worker threads to remove any DBUG injections or DEBUG_SYNC.
|
||||
--source include/stop_slave.inc
|
||||
SET GLOBAL debug_dbug=@old_dbug;
|
||||
SET GLOBAL binlog_format= @old_format;
|
||||
SET GLOBAL slave_parallel_threads=0;
|
||||
SET GLOBAL slave_parallel_threads=10;
|
||||
--source include/start_slave.inc
|
||||
|
||||
|
||||
--connection server_2
|
||||
--source include/stop_slave.inc
|
||||
SET GLOBAL slave_parallel_threads=@old_parallel_threads;
|
||||
|
Reference in New Issue
Block a user