Commit 0fdbdde4 authored by unknown's avatar unknown

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().
parent cb65cee8
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
--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
...@@ -2928,7 +2928,7 @@ MYSQL_BIN_LOG::MYSQL_BIN_LOG(uint *sync_period) ...@@ -2928,7 +2928,7 @@ MYSQL_BIN_LOG::MYSQL_BIN_LOG(uint *sync_period)
bytes_written(0), file_id(1), open_count(1), bytes_written(0), file_id(1), open_count(1),
group_commit_queue(0), group_commit_queue_busy(FALSE), group_commit_queue(0), group_commit_queue_busy(FALSE),
num_commits(0), num_group_commits(0), 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), is_relay_log(0), signal_cnt(0),
checksum_alg_reset(BINLOG_CHECKSUM_ALG_UNDEF), checksum_alg_reset(BINLOG_CHECKSUM_ALG_UNDEF),
relay_log_checksum_alg(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, ...@@ -3122,6 +3122,9 @@ bool MYSQL_BIN_LOG::open(const char *log_name,
DBUG_ENTER("MYSQL_BIN_LOG::open"); DBUG_ENTER("MYSQL_BIN_LOG::open");
DBUG_PRINT("enter",("log_type: %d",(int) log_type_arg)); 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 && if (!is_relay_log && !binlog_background_thread_started &&
start_binlog_background_thread()) start_binlog_background_thread())
DBUG_RETURN(1); DBUG_RETURN(1);
...@@ -5435,6 +5438,10 @@ MYSQL_BIN_LOG::read_state_from_file() ...@@ -5435,6 +5438,10 @@ MYSQL_BIN_LOG::read_state_from_file()
bool opened= false; bool opened= false;
bool inited= false; bool inited= false;
if (state_read)
return 0;
state_read= true;
fn_format(buf, opt_bin_logname, mysql_data_home, ".state", fn_format(buf, opt_bin_logname, mysql_data_home, ".state",
MY_UNPACK_FILENAME); MY_UNPACK_FILENAME);
if ((file_no= mysql_file_open(key_file_binlog_state, buf, if ((file_no= mysql_file_open(key_file_binlog_state, buf,
...@@ -5447,16 +5454,11 @@ MYSQL_BIN_LOG::read_state_from_file() ...@@ -5447,16 +5454,11 @@ MYSQL_BIN_LOG::read_state_from_file()
} }
else else
{ {
rpl_gtid gtid;
/* /*
If the state file does not exist, this is the first server startup If the state file does not exist, this is the first server startup
with GTID enabled. So initialize to empty state. with GTID enabled. So initialize to empty state.
*/ */
gtid.domain_id= global_system_variables.gtid_domain_id; rpl_global_gtid_binlog_state.reset();
gtid.server_id= global_system_variables.server_id;
gtid.seq_no= 0;
rpl_global_gtid_binlog_state.update(&gtid);
err= 0; err= 0;
goto end; goto end;
} }
...@@ -5477,6 +5479,9 @@ end: ...@@ -5477,6 +5479,9 @@ end:
end_io_cache(&cache); end_io_cache(&cache);
if (opened) if (opened)
mysql_file_close(file_no, MYF(0)); 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; return err;
} }
...@@ -8220,12 +8225,12 @@ int TC_LOG_BINLOG::open(const char *opt_name) ...@@ -8220,12 +8225,12 @@ int TC_LOG_BINLOG::open(const char *opt_name)
sql_print_information("Recovering after a crash using %s", opt_name); sql_print_information("Recovering after a crash using %s", opt_name);
error= recover(&log_info, log_name, &log, error= recover(&log_info, log_name, &log,
(Format_description_log_event *)ev); (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 else
error= read_state_from_file(); 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; delete ev;
end_io_cache(&log); end_io_cache(&log);
......
...@@ -507,6 +507,8 @@ class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG ...@@ -507,6 +507,8 @@ class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
*/ */
uint *sync_period_ptr; uint *sync_period_ptr;
uint sync_counter; uint sync_counter;
/* Protect against reading the binlog state file twice. */
bool state_read;
inline uint get_sync_period() inline uint get_sync_period()
{ {
......
...@@ -881,14 +881,6 @@ rpl_binlog_state::find(uint32 domain_id, uint32 server_id) ...@@ -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 uint32
rpl_binlog_state::count() rpl_binlog_state::count()
{ {
...@@ -961,6 +953,14 @@ rpl_binlog_state::get_most_recent_gtid_list(rpl_gtid **list, uint32 *size) ...@@ -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() slave_connection_state::~slave_connection_state()
{ {
my_hash_free(&hash); my_hash_free(&hash);
......
...@@ -936,11 +936,8 @@ gtid_find_binlog_file(slave_connection_state *state, char *out_name) ...@@ -936,11 +936,8 @@ gtid_find_binlog_file(slave_connection_state *state, char *out_name)
binlog_file_entry *list; binlog_file_entry *list;
Gtid_list_log_event *glev= NULL; Gtid_list_log_event *glev= NULL;
const char *errormsg= NULL; const char *errormsg= NULL;
IO_CACHE cache;
File file = (File)-1;
char buf[FN_REFLEN]; char buf[FN_REFLEN];
bzero((char*) &cache, sizeof(cache));
init_alloc_root(&memroot, 10*(FN_REFLEN+sizeof(binlog_file_entry)), 0, init_alloc_root(&memroot, 10*(FN_REFLEN+sizeof(binlog_file_entry)), 0,
MYF(MY_THREAD_SPECIFIC)); MYF(MY_THREAD_SPECIFIC));
if (!(list= get_binlog_list(&memroot))) if (!(list= get_binlog_list(&memroot)))
...@@ -951,6 +948,9 @@ gtid_find_binlog_file(slave_connection_state *state, char *out_name) ...@@ -951,6 +948,9 @@ gtid_find_binlog_file(slave_connection_state *state, char *out_name)
while (list) while (list)
{ {
File file;
IO_CACHE cache;
if (!list->next) if (!list->next)
{ {
/* /*
...@@ -971,8 +971,13 @@ gtid_find_binlog_file(slave_connection_state *state, char *out_name) ...@@ -971,8 +971,13 @@ gtid_find_binlog_file(slave_connection_state *state, char *out_name)
"GTID position in binlog"; "GTID position in binlog";
goto end; goto end;
} }
if ((file= open_binlog(&cache, buf, &errormsg)) == (File)-1 || bzero((char*) &cache, sizeof(cache));
(errormsg= get_gtid_list_event(&cache, &glev))) 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; goto end;
if (!glev || contains_all_slave_gtid(state, glev)) if (!glev || contains_all_slave_gtid(state, glev))
...@@ -1023,11 +1028,6 @@ gtid_find_binlog_file(slave_connection_state *state, char *out_name) ...@@ -1023,11 +1028,6 @@ gtid_find_binlog_file(slave_connection_state *state, char *out_name)
end: end:
if (glev) if (glev)
delete glev; delete glev;
if (file != (File)-1)
{
end_io_cache(&cache);
mysql_file_close(file, MYF(MY_WME));
}
free_root(&memroot, MYF(0)); free_root(&memroot, MYF(0));
return errormsg; return errormsg;
......
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