mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
MDEV-26: Global transaction ID.
Implement test case rpl_gtid_stop_start.test to test normal stop and restart of master and slave mysqld servers. Fix a couple bugs found with the test: - When InnoDB is disabled (no XA), the binlog state was not read when master mysqld starts. - Remove old code that puts a bogus D-S-0 into the initial binlog state, it is not correct in current design. - Fix memory leak in gtid_find_binlog_file().
This commit is contained in:
parent
cb65cee82a
commit
0fdbdde474
6 changed files with 190 additions and 28 deletions
54
mysql-test/suite/rpl/r/rpl_gtid_stop_start.result
Normal file
54
mysql-test/suite/rpl/r/rpl_gtid_stop_start.result
Normal file
|
@ -0,0 +1,54 @@
|
|||
include/rpl_init.inc [topology=1->2]
|
||||
*** Test normal shutdown/restart of slave server configured as a GTID slave. ***
|
||||
CREATE TABLE t1 (a INT PRIMARY KEY);
|
||||
INSERT INTO t1 VALUES (1);
|
||||
include/stop_slave.inc
|
||||
Master_Log_File = 'master-bin.000001'
|
||||
Using_Gtid = '0'
|
||||
CHANGE MASTER TO master_gtid_pos=AUTO;
|
||||
FLUSH LOGS;
|
||||
PURGE BINARY LOGS TO 'master-bin.000002';
|
||||
show binary logs;
|
||||
Log_name File_size
|
||||
master-bin.000002 #
|
||||
INSERT INTO t1 VALUES (2);
|
||||
FLUSH LOGS;
|
||||
INSERT INTO t1 VALUES (3);
|
||||
show binary logs;
|
||||
Log_name File_size
|
||||
master-bin.000002 #
|
||||
master-bin.000003 #
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
a
|
||||
1
|
||||
2
|
||||
3
|
||||
*** Test normal shutdown/restart of master server, check binlog state is preserved. ***
|
||||
SET SESSION gtid_domain_id= 1;
|
||||
INSERT INTO t1 VALUES (4);
|
||||
SHOW BINLOG EVENTS IN 'master-bin.000003' LIMIT 1,1;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000003 # Gtid_list # # [0-1-3]
|
||||
FLUSH LOGS;
|
||||
SHOW BINLOG EVENTS IN 'master-bin.000004' LIMIT 1,1;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000004 # Gtid_list # # [1-1-5,0-1-4]
|
||||
SHOW BINLOG EVENTS IN 'master-bin.000005' LIMIT 1,1;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000005 # Gtid_list # # [1-1-5,0-1-4]
|
||||
show binary logs;
|
||||
Log_name File_size
|
||||
master-bin.000002 #
|
||||
master-bin.000003 #
|
||||
master-bin.000004 #
|
||||
master-bin.000005 #
|
||||
INSERT INTO t1 VALUES(5);
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
a
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
DROP TABLE t1;
|
||||
include/rpl_end.inc
|
101
mysql-test/suite/rpl/t/rpl_gtid_stop_start.test
Normal file
101
mysql-test/suite/rpl/t/rpl_gtid_stop_start.test
Normal file
|
@ -0,0 +1,101 @@
|
|||
--let $rpl_topology=1->2
|
||||
--source include/rpl_init.inc
|
||||
|
||||
--echo *** Test normal shutdown/restart of slave server configured as a GTID slave. ***
|
||||
|
||||
--connection server_1
|
||||
CREATE TABLE t1 (a INT PRIMARY KEY);
|
||||
INSERT INTO t1 VALUES (1);
|
||||
--save_master_pos
|
||||
|
||||
--connection server_2
|
||||
--sync_with_master
|
||||
--source include/stop_slave.inc
|
||||
|
||||
--let $status_items= Master_Log_File,Using_Gtid
|
||||
--source include/show_slave_status.inc
|
||||
|
||||
CHANGE MASTER TO master_gtid_pos=AUTO;
|
||||
|
||||
# Now try to restart the slave mysqld server without starting the slave first
|
||||
# threads after the CHANGE MASTER.
|
||||
# When the slave restarts, it should reconnect using GTID.
|
||||
# We test that it really uses GTID by purging on the master the
|
||||
# old binlog the slave would need if connecting with old style
|
||||
# file name/offset.
|
||||
|
||||
--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
|
||||
wait
|
||||
EOF
|
||||
--shutdown_server 30
|
||||
--source include/wait_until_disconnected.inc
|
||||
|
||||
--connection server_1
|
||||
FLUSH LOGS;
|
||||
PURGE BINARY LOGS TO 'master-bin.000002';
|
||||
--source include/show_binary_logs.inc
|
||||
INSERT INTO t1 VALUES (2);
|
||||
FLUSH LOGS;
|
||||
INSERT INTO t1 VALUES (3);
|
||||
--source include/show_binary_logs.inc
|
||||
|
||||
# Let the slave mysqld server start again.
|
||||
--remove_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
|
||||
--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
|
||||
restart: --skip-slave-start=0
|
||||
EOF
|
||||
|
||||
--connection server_2
|
||||
--enable_reconnect
|
||||
--source include/wait_until_connected_again.inc
|
||||
|
||||
--let $wait_condition= SELECT COUNT(*) = 3 FROM t1
|
||||
--source include/wait_condition.inc
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
|
||||
|
||||
--echo *** Test normal shutdown/restart of master server, check binlog state is preserved. ***
|
||||
|
||||
--connection server_1
|
||||
SET SESSION gtid_domain_id= 1;
|
||||
INSERT INTO t1 VALUES (4);
|
||||
--replace_column 2 # 4 # 5 #
|
||||
SHOW BINLOG EVENTS IN 'master-bin.000003' LIMIT 1,1;
|
||||
FLUSH LOGS;
|
||||
--replace_column 2 # 4 # 5 #
|
||||
SHOW BINLOG EVENTS IN 'master-bin.000004' LIMIT 1,1;
|
||||
|
||||
--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||
wait
|
||||
EOF
|
||||
--shutdown_server 30
|
||||
--source include/wait_until_disconnected.inc
|
||||
|
||||
--remove_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||
--write_file $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
|
||||
restart
|
||||
EOF
|
||||
|
||||
--connection default
|
||||
--enable_reconnect
|
||||
--source include/wait_until_connected_again.inc
|
||||
--connection server_1
|
||||
--enable_reconnect
|
||||
--source include/wait_until_connected_again.inc
|
||||
|
||||
--replace_column 2 # 4 # 5 #
|
||||
SHOW BINLOG EVENTS IN 'master-bin.000005' LIMIT 1,1;
|
||||
--source include/show_binary_logs.inc
|
||||
|
||||
INSERT INTO t1 VALUES(5);
|
||||
|
||||
--connection server_2
|
||||
--let $wait_condition= SELECT COUNT(*) = 5 FROM t1
|
||||
--source include/wait_condition.inc
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
|
||||
|
||||
--connection server_1
|
||||
DROP TABLE t1;
|
||||
|
||||
--source include/rpl_end.inc
|
25
sql/log.cc
25
sql/log.cc
|
@ -2928,7 +2928,7 @@ MYSQL_BIN_LOG::MYSQL_BIN_LOG(uint *sync_period)
|
|||
bytes_written(0), file_id(1), open_count(1),
|
||||
group_commit_queue(0), group_commit_queue_busy(FALSE),
|
||||
num_commits(0), num_group_commits(0),
|
||||
sync_period_ptr(sync_period), sync_counter(0),
|
||||
sync_period_ptr(sync_period), sync_counter(0), state_read(false),
|
||||
is_relay_log(0), signal_cnt(0),
|
||||
checksum_alg_reset(BINLOG_CHECKSUM_ALG_UNDEF),
|
||||
relay_log_checksum_alg(BINLOG_CHECKSUM_ALG_UNDEF),
|
||||
|
@ -3122,6 +3122,9 @@ bool MYSQL_BIN_LOG::open(const char *log_name,
|
|||
DBUG_ENTER("MYSQL_BIN_LOG::open");
|
||||
DBUG_PRINT("enter",("log_type: %d",(int) log_type_arg));
|
||||
|
||||
if (!is_relay_log && read_state_from_file())
|
||||
DBUG_RETURN(1);
|
||||
|
||||
if (!is_relay_log && !binlog_background_thread_started &&
|
||||
start_binlog_background_thread())
|
||||
DBUG_RETURN(1);
|
||||
|
@ -5435,6 +5438,10 @@ MYSQL_BIN_LOG::read_state_from_file()
|
|||
bool opened= false;
|
||||
bool inited= false;
|
||||
|
||||
if (state_read)
|
||||
return 0;
|
||||
state_read= true;
|
||||
|
||||
fn_format(buf, opt_bin_logname, mysql_data_home, ".state",
|
||||
MY_UNPACK_FILENAME);
|
||||
if ((file_no= mysql_file_open(key_file_binlog_state, buf,
|
||||
|
@ -5447,16 +5454,11 @@ MYSQL_BIN_LOG::read_state_from_file()
|
|||
}
|
||||
else
|
||||
{
|
||||
rpl_gtid gtid;
|
||||
|
||||
/*
|
||||
If the state file does not exist, this is the first server startup
|
||||
with GTID enabled. So initialize to empty state.
|
||||
*/
|
||||
gtid.domain_id= global_system_variables.gtid_domain_id;
|
||||
gtid.server_id= global_system_variables.server_id;
|
||||
gtid.seq_no= 0;
|
||||
rpl_global_gtid_binlog_state.update(>id);
|
||||
rpl_global_gtid_binlog_state.reset();
|
||||
err= 0;
|
||||
goto end;
|
||||
}
|
||||
|
@ -5477,6 +5479,9 @@ end:
|
|||
end_io_cache(&cache);
|
||||
if (opened)
|
||||
mysql_file_close(file_no, MYF(0));
|
||||
/* Pick the next unused seq_no from the loaded binlog state. */
|
||||
bump_seq_no_counter_if_needed(
|
||||
rpl_global_gtid_binlog_state.seq_no_from_state());
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -8220,12 +8225,12 @@ int TC_LOG_BINLOG::open(const char *opt_name)
|
|||
sql_print_information("Recovering after a crash using %s", opt_name);
|
||||
error= recover(&log_info, log_name, &log,
|
||||
(Format_description_log_event *)ev);
|
||||
/* Pick the next unused seq_no from the recovered binlog state. */
|
||||
bump_seq_no_counter_if_needed(
|
||||
rpl_global_gtid_binlog_state.seq_no_from_state());
|
||||
}
|
||||
else
|
||||
error= read_state_from_file();
|
||||
/* Pick the next unused seq_no from the loaded/recovered binlog state. */
|
||||
bump_seq_no_counter_if_needed(
|
||||
rpl_global_gtid_binlog_state.seq_no_from_state());
|
||||
|
||||
delete ev;
|
||||
end_io_cache(&log);
|
||||
|
|
|
@ -507,6 +507,8 @@ class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
|
|||
*/
|
||||
uint *sync_period_ptr;
|
||||
uint sync_counter;
|
||||
/* Protect against reading the binlog state file twice. */
|
||||
bool state_read;
|
||||
|
||||
inline uint get_sync_period()
|
||||
{
|
||||
|
|
|
@ -881,14 +881,6 @@ rpl_binlog_state::find(uint32 domain_id, uint32 server_id)
|
|||
}
|
||||
|
||||
|
||||
slave_connection_state::slave_connection_state()
|
||||
{
|
||||
my_hash_init(&hash, &my_charset_bin, 32,
|
||||
offsetof(rpl_gtid, domain_id), sizeof(uint32), NULL, my_free,
|
||||
HASH_UNIQUE);
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
rpl_binlog_state::count()
|
||||
{
|
||||
|
@ -961,6 +953,14 @@ rpl_binlog_state::get_most_recent_gtid_list(rpl_gtid **list, uint32 *size)
|
|||
}
|
||||
|
||||
|
||||
slave_connection_state::slave_connection_state()
|
||||
{
|
||||
my_hash_init(&hash, &my_charset_bin, 32,
|
||||
offsetof(rpl_gtid, domain_id), sizeof(uint32), NULL, my_free,
|
||||
HASH_UNIQUE);
|
||||
}
|
||||
|
||||
|
||||
slave_connection_state::~slave_connection_state()
|
||||
{
|
||||
my_hash_free(&hash);
|
||||
|
|
|
@ -936,11 +936,8 @@ gtid_find_binlog_file(slave_connection_state *state, char *out_name)
|
|||
binlog_file_entry *list;
|
||||
Gtid_list_log_event *glev= NULL;
|
||||
const char *errormsg= NULL;
|
||||
IO_CACHE cache;
|
||||
File file = (File)-1;
|
||||
char buf[FN_REFLEN];
|
||||
|
||||
bzero((char*) &cache, sizeof(cache));
|
||||
init_alloc_root(&memroot, 10*(FN_REFLEN+sizeof(binlog_file_entry)), 0,
|
||||
MYF(MY_THREAD_SPECIFIC));
|
||||
if (!(list= get_binlog_list(&memroot)))
|
||||
|
@ -951,6 +948,9 @@ gtid_find_binlog_file(slave_connection_state *state, char *out_name)
|
|||
|
||||
while (list)
|
||||
{
|
||||
File file;
|
||||
IO_CACHE cache;
|
||||
|
||||
if (!list->next)
|
||||
{
|
||||
/*
|
||||
|
@ -971,8 +971,13 @@ gtid_find_binlog_file(slave_connection_state *state, char *out_name)
|
|||
"GTID position in binlog";
|
||||
goto end;
|
||||
}
|
||||
if ((file= open_binlog(&cache, buf, &errormsg)) == (File)-1 ||
|
||||
(errormsg= get_gtid_list_event(&cache, &glev)))
|
||||
bzero((char*) &cache, sizeof(cache));
|
||||
if ((file= open_binlog(&cache, buf, &errormsg)) == (File)-1)
|
||||
goto end;
|
||||
errormsg= get_gtid_list_event(&cache, &glev);
|
||||
end_io_cache(&cache);
|
||||
mysql_file_close(file, MYF(MY_WME));
|
||||
if (errormsg)
|
||||
goto end;
|
||||
|
||||
if (!glev || contains_all_slave_gtid(state, glev))
|
||||
|
@ -1023,11 +1028,6 @@ gtid_find_binlog_file(slave_connection_state *state, char *out_name)
|
|||
end:
|
||||
if (glev)
|
||||
delete glev;
|
||||
if (file != (File)-1)
|
||||
{
|
||||
end_io_cache(&cache);
|
||||
mysql_file_close(file, MYF(MY_WME));
|
||||
}
|
||||
|
||||
free_root(&memroot, MYF(0));
|
||||
return errormsg;
|
||||
|
|
Loading…
Reference in a new issue