diff options
-rw-r--r-- | mysql-test/suite/rpl/r/rpl_gtid_stop_start.result | 54 | ||||
-rw-r--r-- | mysql-test/suite/rpl/t/rpl_gtid_stop_start.test | 101 | ||||
-rw-r--r-- | sql/log.cc | 25 | ||||
-rw-r--r-- | sql/log.h | 2 | ||||
-rw-r--r-- | sql/rpl_gtid.cc | 16 | ||||
-rw-r--r-- | sql/sql_repl.cc | 20 |
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(>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); 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; |