1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-07 00:04:31 +03:00
Files
mariadb/mysql-test/suite/binlog/t/binlog_truncate_multi_log_unsafe.test
Brandon Nesterenko eb4458e993 MDEV-33465: an option to enable semisync recovery
The current semi-sync binlog fail-over recovery process uses
rpl_semi_sync_slave_enabled==TRUE as its condition to truncate a
primary server’s binlog, as it is anticipating the server to re-join
a replication topology as a replica. However, for servers configured
with both rpl_semi_sync_master_enabled=1 and
rpl_semi_sync_slave_enabled=1, if a primary is just re-started (i.e.
retaining its role as master), it can truncate its binlog to drop
transactions which its replica(s) has already received and executed.
If this happens, when the replica reconnects, its gtid_slave_pos can
be ahead of the recovered primary’s gtid_binlog_pos, resulting in an
error state where the replica’s state is ahead of the primary’s.

This patch changes the condition for semi-sync recovery to truncate
the binlog to instead use the configuration variable
--init-rpl-role, when set to SLAVE. This allows for both
rpl_semi_sync_master_enabled and rpl_semi_sync_slave_enabled to be
set for a primary that is restarted, and no transactions will be
lost, so long as --init-rpl-role is not set to SLAVE.

Reviewed By:
============
Sergei Golubchik <serg@mariadb.com>
2024-07-05 19:53:57 -06:00

121 lines
4.1 KiB
Plaintext

# ==== Purpose ====
# The test verifies attempt to recover by the semisync slave server whose
# binlog is unsafe for truncation.
#
# ==== Implementation ====
# 2 binlog files are created with the 1st one destined to be the binlog
# checkpoint file for recovery.
# The final group of events is replication unsafe (myisam INSERT).
# Therefore the semisync slave recovery may not.
#
# Steps:
# 0 - Set max_binlog_size= 4096, to help an insert into a
# transaction table 'ti' get binlog rotated while the
# transaction won't be committed, being stopped at
# a prior to commit debug_sync point
# 1 - insert into a non-transactional 'tm' table completes with
# binary logging as well
# 2 - kill and attempt to restart the server as semisync slave that
# must produce an expected unsafe-to-recover error
# 3 - complete the test with a normal restart that successfully finds and
# commits the transaction in doubt.
#
# ==== References ====
#
# MDEV-21117: recovery for --rpl-semi-sync-slave-enabled server
#
--source include/have_innodb.inc
--source include/have_debug_sync.inc
--source include/have_binlog_format_row.inc
SET @@global.max_binlog_size= 4096;
call mtr.add_suppression("Table '.*tm' is marked as crashed and should be repaired");
call mtr.add_suppression("Got an error from unknown thread");
call mtr.add_suppression("Checking table: '.*tm'");
call mtr.add_suppression("Recovering table: '.*tm'");
call mtr.add_suppression("Cannot truncate the binary log to file");
call mtr.add_suppression("Crash recovery failed");
call mtr.add_suppression("Can.t init tc log");
call mtr.add_suppression("Aborting");
call mtr.add_suppression("Found 1 prepared transactions");
call mtr.add_suppression("mysqld: Table.*tm.*is marked as crashed");
call mtr.add_suppression("Checking table.*tm");
RESET MASTER;
FLUSH LOGS;
SET @@global.sync_binlog=1;
CREATE TABLE ti (a INT PRIMARY KEY, b MEDIUMTEXT) ENGINE=Innodb;
CREATE TABLE tm (f INT) ENGINE=MYISAM;
--let $row_count = 5
--let $i = `select $row_count-2`
--disable_query_log
while ($i)
{
--eval INSERT INTO ti VALUES ($i, REPEAT("x", 1))
--dec $i
}
--enable_query_log
INSERT INTO tm VALUES(1);
connect(master1,localhost,root,,);
connect(master2,localhost,root,,);
connect(master3,localhost,root,,);
--connection master1
# The 1st trx binlogs, rotate binlog and hold on before committing at engine
SET DEBUG_SYNC= "commit_after_release_LOCK_after_binlog_sync SIGNAL master1_ready WAIT_FOR master1_go_never_arrives";
--send_eval INSERT INTO ti VALUES ($row_count - 1, REPEAT("x", 4100))
--connection master2
SET DEBUG_SYNC= "now WAIT_FOR master1_ready";
# The 2nd trx for recovery, it does not rotate binlog
SET DEBUG_SYNC= "commit_before_get_LOCK_commit_ordered SIGNAL master2_ready WAIT_FOR master2_go_never_arrives";
--send_eval INSERT INTO ti VALUES ($row_count, REPEAT("x", 1))
--connection master3
SET DEBUG_SYNC= "now WAIT_FOR master2_ready";
SET DEBUG_SYNC= "commit_before_get_LOCK_after_binlog_sync SIGNAL master3_ready";
--send INSERT INTO tm VALUES (2)
--connection default
SET DEBUG_SYNC= "now WAIT_FOR master3_ready";
--echo # The gtid binlog state prior the crash must be restored at the end of the test;
SELECT @@global.gtid_binlog_state;
--source include/kill_mysqld.inc
#
# Server restarts
#
--echo # Failed restart as the semisync slave
--error 1
--exec $MYSQLD_LAST_CMD --init-rpl-role=SLAVE >> $MYSQLTEST_VARDIR/log/mysqld.1.err 2>&1
--echo # Normal restart
--source include/start_mysqld.inc
# Check error log for correct messages.
let $log_error_ = $MYSQLTEST_VARDIR/log/mysqld.1.err;
--let SEARCH_FILE=$log_error_
--let SEARCH_PATTERN=Cannot truncate the binary log to file
--source include/search_pattern_in_file.inc
--echo # Proof that the in-doubt transactions are recovered by the 2nd normal server restart
--eval SELECT COUNT(*) = $row_count as 'True' FROM ti
# myisam table may require repair (which is not tested here)
--disable_warnings
SELECT COUNT(*) <= 1 FROM tm;
--enable_warnings
--echo # The gtid binlog state prior the crash is restored now
SELECT @@GLOBAL.gtid_binlog_state;
SELECT @@GLOBAL.gtid_binlog_pos;
--echo # Cleanup
DROP TABLE ti, tm;
--echo End of test