summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/suite/rpl/r/rpl_gtid_stop_start.result54
-rw-r--r--mysql-test/suite/rpl/t/rpl_gtid_stop_start.test101
-rw-r--r--sql/log.cc25
-rw-r--r--sql/log.h2
-rw-r--r--sql/rpl_gtid.cc16
-rw-r--r--sql/sql_repl.cc20
6 files changed, 190 insertions, 28 deletions
diff --git a/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result b/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result
new file mode 100644
index 00000000000..9d02ef0d5f9
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result
@@ -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
diff --git a/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test b/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test
new file mode 100644
index 00000000000..78e04d2d8d6
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test
@@ -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
diff --git a/sql/log.cc b/sql/log.cc
index f17fb0ff619..9120a1224a6 100644
--- a/sql/log.cc
+++ b/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(&gtid);
+ 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);
diff --git a/sql/log.h b/sql/log.h
index 3f49365b2da..c9d3b47e837 100644
--- a/sql/log.h
+++ b/sql/log.h
@@ -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()
{
diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc
index 55e2f039562..cdb948f3618 100644
--- a/sql/rpl_gtid.cc
+++ b/sql/rpl_gtid.cc
@@ -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);
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index f6f47399271..0f8dbdd5112 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -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;