MDEV-26: Global transaction ID.
Add tests crashing the slave in the middle of replication and checking that replication picks-up again on restart in a crash-safe way. Fix silly code that causes crash by inserting uninitialised data into a hash.
This commit is contained in:
parent
9303ecd022
commit
5aaf73fcaa
@ -56,5 +56,36 @@ a
|
|||||||
1
|
1
|
||||||
2
|
2
|
||||||
3
|
3
|
||||||
|
*** Test crashing slave at various points and check that it recovers crash-safe. ***
|
||||||
|
include/stop_slave.inc
|
||||||
|
SET GLOBAL debug_dbug="+d,inject_crash_before_write_rpl_slave_state";
|
||||||
|
START SLAVE;
|
||||||
|
INSERT INTO t1 VALUES (4);
|
||||||
|
include/stop_slave.inc
|
||||||
|
SET GLOBAL debug_dbug="+d,crash_commit_before";
|
||||||
|
START SLAVE;
|
||||||
|
INSERT INTO t1 VALUES (5);
|
||||||
|
include/stop_slave.inc
|
||||||
|
SET GLOBAL debug_dbug="+d,crash_commit_after";
|
||||||
|
START SLAVE;
|
||||||
|
INSERT INTO t1 VALUES (6);
|
||||||
|
include/stop_slave.inc
|
||||||
|
SET GLOBAL debug_dbug="+d,inject_crash_before_flush_rli";
|
||||||
|
START SLAVE;
|
||||||
|
INSERT INTO t1 VALUES (7);
|
||||||
|
include/stop_slave.inc
|
||||||
|
SET GLOBAL debug_dbug="+d,inject_crash_after_flush_rli";
|
||||||
|
START SLAVE;
|
||||||
|
INSERT INTO t1 VALUES (8);
|
||||||
|
SELECT * FROM t1 ORDER BY a;
|
||||||
|
a
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
5
|
||||||
|
6
|
||||||
|
7
|
||||||
|
8
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
include/rpl_end.inc
|
include/rpl_end.inc
|
||||||
|
@ -124,6 +124,140 @@ SHOW BINLOG EVENTS IN 'master-bin.000004' LIMIT 1,1;
|
|||||||
--sync_with_master
|
--sync_with_master
|
||||||
SELECT * FROM t1 ORDER BY a;
|
SELECT * FROM t1 ORDER BY a;
|
||||||
|
|
||||||
|
|
||||||
|
--echo *** Test crashing slave at various points and check that it recovers crash-safe. ***
|
||||||
|
|
||||||
|
# Crash the slave just before updating mysql.rpl_slave_state table.
|
||||||
|
--source include/stop_slave.inc
|
||||||
|
--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
|
||||||
|
wait
|
||||||
|
EOF
|
||||||
|
# We do not have to save @@GLOBAL.debug_dbug, it is reset when slave crashes.
|
||||||
|
SET GLOBAL debug_dbug="+d,inject_crash_before_write_rpl_slave_state";
|
||||||
|
START SLAVE;
|
||||||
|
|
||||||
|
--connection server_1
|
||||||
|
INSERT INTO t1 VALUES (4);
|
||||||
|
|
||||||
|
--connection server_2
|
||||||
|
--source include/wait_until_disconnected.inc
|
||||||
|
|
||||||
|
--remove_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
|
||||||
|
--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
|
||||||
|
restart: --skip-slave-start=0
|
||||||
|
EOF
|
||||||
|
|
||||||
|
--enable_reconnect
|
||||||
|
--source include/wait_until_connected_again.inc
|
||||||
|
|
||||||
|
--let $wait_condition= SELECT COUNT(*) = 4 FROM t1
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
|
# Crash the slave just before committing.
|
||||||
|
--source include/stop_slave.inc
|
||||||
|
--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
|
||||||
|
wait
|
||||||
|
EOF
|
||||||
|
SET GLOBAL debug_dbug="+d,crash_commit_before";
|
||||||
|
START SLAVE;
|
||||||
|
|
||||||
|
--connection server_1
|
||||||
|
INSERT INTO t1 VALUES (5);
|
||||||
|
|
||||||
|
--connection server_2
|
||||||
|
--source include/wait_until_disconnected.inc
|
||||||
|
|
||||||
|
--remove_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
|
||||||
|
--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
|
||||||
|
restart: --skip-slave-start=0
|
||||||
|
EOF
|
||||||
|
|
||||||
|
--enable_reconnect
|
||||||
|
--source include/wait_until_connected_again.inc
|
||||||
|
|
||||||
|
--let $wait_condition= SELECT COUNT(*) = 5 FROM t1
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
|
# Crash the slave just after committing.
|
||||||
|
--source include/stop_slave.inc
|
||||||
|
--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
|
||||||
|
wait
|
||||||
|
EOF
|
||||||
|
SET GLOBAL debug_dbug="+d,crash_commit_after";
|
||||||
|
START SLAVE;
|
||||||
|
|
||||||
|
--connection server_1
|
||||||
|
INSERT INTO t1 VALUES (6);
|
||||||
|
|
||||||
|
--connection server_2
|
||||||
|
--source include/wait_until_disconnected.inc
|
||||||
|
|
||||||
|
--remove_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
|
||||||
|
--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
|
||||||
|
restart: --skip-slave-start=0
|
||||||
|
EOF
|
||||||
|
|
||||||
|
--enable_reconnect
|
||||||
|
--source include/wait_until_connected_again.inc
|
||||||
|
|
||||||
|
--let $wait_condition= SELECT COUNT(*) = 6 FROM t1
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
|
# Crash the slave just before updating relay-log.info
|
||||||
|
--source include/stop_slave.inc
|
||||||
|
--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
|
||||||
|
wait
|
||||||
|
EOF
|
||||||
|
SET GLOBAL debug_dbug="+d,inject_crash_before_flush_rli";
|
||||||
|
START SLAVE;
|
||||||
|
|
||||||
|
--connection server_1
|
||||||
|
INSERT INTO t1 VALUES (7);
|
||||||
|
|
||||||
|
--connection server_2
|
||||||
|
--source include/wait_until_disconnected.inc
|
||||||
|
|
||||||
|
--remove_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
|
||||||
|
--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
|
||||||
|
restart: --skip-slave-start=0
|
||||||
|
EOF
|
||||||
|
|
||||||
|
--enable_reconnect
|
||||||
|
--source include/wait_until_connected_again.inc
|
||||||
|
|
||||||
|
--let $wait_condition= SELECT COUNT(*) = 7 FROM t1
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
|
# Crash the slave just after updating relay-log.info
|
||||||
|
--source include/stop_slave.inc
|
||||||
|
--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
|
||||||
|
wait
|
||||||
|
EOF
|
||||||
|
SET GLOBAL debug_dbug="+d,inject_crash_after_flush_rli";
|
||||||
|
START SLAVE;
|
||||||
|
|
||||||
|
--connection server_1
|
||||||
|
INSERT INTO t1 VALUES (8);
|
||||||
|
|
||||||
|
--connection server_2
|
||||||
|
--source include/wait_until_disconnected.inc
|
||||||
|
|
||||||
|
--remove_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
|
||||||
|
--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
|
||||||
|
restart: --skip-slave-start=0
|
||||||
|
EOF
|
||||||
|
|
||||||
|
--enable_reconnect
|
||||||
|
--source include/wait_until_connected_again.inc
|
||||||
|
|
||||||
|
--let $wait_condition= SELECT COUNT(*) = 8 FROM t1
|
||||||
|
--source include/wait_condition.inc
|
||||||
|
|
||||||
|
|
||||||
|
# Check that everything was replicated correctly.
|
||||||
|
SELECT * FROM t1 ORDER BY a;
|
||||||
|
|
||||||
|
|
||||||
--connection server_1
|
--connection server_1
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
@ -329,6 +329,7 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id,
|
|||||||
table->field[1]->store(sub_id, true);
|
table->field[1]->store(sub_id, true);
|
||||||
table->field[2]->store((ulonglong)gtid->server_id, true);
|
table->field[2]->store((ulonglong)gtid->server_id, true);
|
||||||
table->field[3]->store(gtid->seq_no, true);
|
table->field[3]->store(gtid->seq_no, true);
|
||||||
|
DBUG_EXECUTE_IF("inject_crash_before_write_rpl_slave_state", DBUG_SUICIDE(););
|
||||||
if ((err= table->file->ha_write_row(table->record[0])))
|
if ((err= table->file->ha_write_row(table->record[0])))
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
|
@ -1246,7 +1246,9 @@ void Relay_log_info::stmt_done(my_off_t event_master_log_pos,
|
|||||||
DBA aware of the problem in the error log.
|
DBA aware of the problem in the error log.
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
DBUG_EXECUTE_IF("inject_crash_before_flush_rli", DBUG_SUICIDE(););
|
||||||
flush_relay_log_info(this);
|
flush_relay_log_info(this);
|
||||||
|
DBUG_EXECUTE_IF("inject_crash_after_flush_rli", DBUG_SUICIDE(););
|
||||||
/*
|
/*
|
||||||
Note that Rotate_log_event::do_apply_event() does not call this
|
Note that Rotate_log_event::do_apply_event() does not call this
|
||||||
function, so there is no chance that a fake rotate event resets
|
function, so there is no chance that a fake rotate event resets
|
||||||
@ -1453,6 +1455,10 @@ rpl_load_gtid_slave_state(THD *thd)
|
|||||||
entry= (struct local_element *)rec;
|
entry= (struct local_element *)rec;
|
||||||
if (entry->sub_id >= sub_id)
|
if (entry->sub_id >= sub_id)
|
||||||
continue;
|
continue;
|
||||||
|
entry->sub_id= sub_id;
|
||||||
|
DBUG_ASSERT(entry->gtid.domain_id == domain_id);
|
||||||
|
entry->gtid.server_id= server_id;
|
||||||
|
entry->gtid.seq_no= seq_no;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1462,17 +1468,16 @@ rpl_load_gtid_slave_state(THD *thd)
|
|||||||
err= 1;
|
err= 1;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
entry->sub_id= sub_id;
|
||||||
|
entry->gtid.domain_id= domain_id;
|
||||||
|
entry->gtid.server_id= server_id;
|
||||||
|
entry->gtid.seq_no= seq_no;
|
||||||
if ((err= my_hash_insert(&hash, (uchar *)entry)))
|
if ((err= my_hash_insert(&hash, (uchar *)entry)))
|
||||||
{
|
{
|
||||||
my_free(entry);
|
my_free(entry);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
entry->sub_id= sub_id;
|
|
||||||
entry->gtid.domain_id= domain_id;
|
|
||||||
entry->gtid.server_id= server_id;
|
|
||||||
entry->gtid.seq_no= seq_no;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl_global_gtid_slave_state.lock();
|
rpl_global_gtid_slave_state.lock();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user