diff options
author | unknown <knielsen@knielsen-hq.org> | 2013-02-15 15:55:17 +0100 |
---|---|---|
committer | unknown <knielsen@knielsen-hq.org> | 2013-02-15 15:55:17 +0100 |
commit | 1c6271b36a8a8b85e5af87915fc5d680e2c10575 (patch) | |
tree | 155c08d309c42c3160e35c64dd55c4bf83db9ce0 /sql | |
parent | 2d723aa9ebc38b672b2ccc4b42efb223e858978a (diff) | |
download | mariadb-git-1c6271b36a8a8b85e5af87915fc5d680e2c10575.tar.gz |
MDEV-26: Global Transaction ID.
Implement CHANGE MASTER TO ... MASTER_GTID_POS = "x-y-z,a-b-c".
Diffstat (limited to 'sql')
-rw-r--r-- | sql/log_event.cc | 67 | ||||
-rw-r--r-- | sql/log_event.h | 4 | ||||
-rw-r--r-- | sql/share/errmsg-utf8.txt | 6 | ||||
-rw-r--r-- | sql/slave.cc | 3 | ||||
-rw-r--r-- | sql/sql_lex.h | 2 | ||||
-rw-r--r-- | sql/sql_repl.cc | 36 |
6 files changed, 108 insertions, 10 deletions
diff --git a/sql/log_event.cc b/sql/log_event.cc index 6d87d66c740..91d569d284d 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -6076,13 +6076,12 @@ rpl_slave_state::init() inited= true; } + void -rpl_slave_state::deinit() +rpl_slave_state::truncate_hash() { uint32 i; - if (!inited) - return; for (i= 0; i < hash.records; ++i) { element *e= (element *)my_hash_element(&hash, i); @@ -6094,8 +6093,17 @@ rpl_slave_state::deinit() my_free(l); l= next; } - /* The element itself is freed by my_hash_free(). */ + /* The element itself is freed by the hash element free function. */ } + my_hash_reset(&hash); +} + +void +rpl_slave_state::deinit() +{ + if (!inited) + return; + truncate_hash(); my_hash_free(&hash); mysql_mutex_destroy(&LOCK_slave_state); } @@ -6148,6 +6156,42 @@ rpl_slave_state::get_element(uint32 domain_id) #ifdef MYSQL_SERVER #ifdef HAVE_REPLICATION +int +rpl_slave_state::truncate_state_table(THD *thd) +{ + TABLE_LIST tlist; + int err= 0; + TABLE *table; + + mysql_reset_thd_for_next_command(thd, 0); + + tlist.init_one_table(STRING_WITH_LEN("mysql"), + rpl_gtid_slave_state_table_name.str, + rpl_gtid_slave_state_table_name.length, + NULL, TL_WRITE); + if (!(err= open_and_lock_tables(thd, &tlist, FALSE, 0))) + { + table= tlist.table; + err= table->file->ha_truncate(); + + if (err) + { + ha_rollback_trans(thd, FALSE); + close_thread_tables(thd); + ha_rollback_trans(thd, TRUE); + } + else + { + ha_commit_trans(thd, FALSE); + close_thread_tables(thd); + ha_commit_trans(thd, TRUE); + } + } + + return err; +} + + /* Write a gtid to the replication slave state table. @@ -6442,13 +6486,23 @@ gtid_parser_helper(char **ptr, char *end, rpl_gtid *out_gtid) Update the slave replication state with the GTID position obtained from master when connecting with old-style (filename,offset) position. + If RESET is true then all existing entries are removed. Otherwise only + domain_ids mentioned in the STATE_FROM_MASTER are changed. + Returns 0 if ok, non-zero if error. */ int -rpl_slave_state::load(THD *thd, char *state_from_master) +rpl_slave_state::load(THD *thd, char *state_from_master, size_t len, + bool reset) { - char *end= state_from_master + strlen(state_from_master); + char *end= state_from_master + len; + if (reset) + { + if (truncate_state_table(thd)) + return 1; + truncate_hash(); + } for (;;) { rpl_gtid gtid; @@ -6463,6 +6517,7 @@ rpl_slave_state::load(THD *thd, char *state_from_master) break; if (*state_from_master != ',') return 1; + ++state_from_master; } return 0; } diff --git a/sql/log_event.h b/sql/log_event.h index b00d54714a5..385ff1563c5 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -3003,13 +3003,15 @@ struct rpl_slave_state void init(); void deinit(); + void truncate_hash(); ulong count() const { return hash.records; } int update(uint32 domain_id, uint32 server_id, uint64 sub_id, uint64 seq_no); + int truncate_state_table(THD *thd); int record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id, bool in_transaction); uint64 next_subid(uint32 domain_id); int tostring(String *dest, rpl_gtid *extra_gtids, uint32 num_extra); - int load(THD *thd, char *state_from_master); + int load(THD *thd, char *state_from_master, size_t len, bool reset); bool is_empty(); void lock() { DBUG_ASSERT(inited); mysql_mutex_lock(&LOCK_slave_state); } diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index a6ebebeae39..9161569f73c 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -6599,4 +6599,8 @@ ER_CANT_START_STOP_SLAVE ER_SLAVE_STARTED eng "SLAVE '%.*s' started" ER_SLAVE_STOPPED - eng "SLAVE '%.*s' stopped"
\ No newline at end of file + eng "SLAVE '%.*s' stopped" +ER_FAILED_GTID_STATE_INIT + eng "Failed initializing replication GTID state" +ER_INCORRECT_GTID_STATE + eng "Could not parse GTID list for MASTER_GTID_POS" diff --git a/sql/slave.cc b/sql/slave.cc index 3e2f1898294..33455986008 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -1864,7 +1864,8 @@ after_set_capability: (master_row= mysql_fetch_row(master_res)) && (master_row[0] != NULL)) { - rpl_global_gtid_slave_state.load(mi->io_thd, master_row[0]); + rpl_global_gtid_slave_state.load(mi->io_thd, master_row[0], + strlen(master_row[0]), false); } else if (check_io_slave_killed(mi->io_thd, mi, NULL)) goto slave_killed_err; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 426fb497c39..f83df69a935 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -315,6 +315,8 @@ struct LEX_MASTER_INFO host= user= password= log_file_name= ssl_key= ssl_cert= ssl_ca= ssl_capath= ssl_cipher= relay_log_name= 0; pos= relay_log_pos= server_id= port= connect_retry= 0; + gtid_pos_str.str= NULL; + gtid_pos_str.length= 0; gtid_pos_auto= FALSE; heartbeat_period= 0; ssl= ssl_verify_server_cert= heartbeat_opt= diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index e2b360611df..bd491b17e7c 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -2231,6 +2231,7 @@ bool change_master(THD* thd, Master_info* mi, bool *master_info_added) char relay_log_info_file_tmp[FN_REFLEN]; my_off_t saved_log_pos; LEX_MASTER_INFO* lex_mi= &thd->lex->mi; + slave_connection_state tmp_slave_state; DBUG_ENTER("change_master"); *master_info_added= false; @@ -2261,6 +2262,27 @@ bool change_master(THD* thd, Master_info* mi, bool *master_info_added) goto err; } + if (lex_mi->gtid_pos_str.str) + { + if (master_info_index->give_error_if_slave_running()) + { + ret= TRUE; + goto err; + } + /* + First load it into a dummy object, to check for parse errors. + We do not want to wipe the previous state if there is an error + in the syntax of the new state! + */ + if (tmp_slave_state.load(lex_mi->gtid_pos_str.str, + lex_mi->gtid_pos_str.length)) + { + my_error(ER_INCORRECT_GTID_STATE, MYF(0)); + ret= TRUE; + goto err; + } + } + thd_proc_info(thd, "Changing master"); create_logfile_name_with_suffix(master_info_file_tmp, @@ -2426,7 +2448,7 @@ bool change_master(THD* thd, Master_info* mi, bool *master_info_added) mi->rli.group_relay_log_pos= mi->rli.event_relay_log_pos= lex_mi->relay_log_pos; } - if (lex_mi->gtid_pos_auto) + if (lex_mi->gtid_pos_auto || lex_mi->gtid_pos_str.str) mi->gtid_pos_auto= true; else if (lex_mi->gtid_pos_str.str || lex_mi->log_file_name || lex_mi->pos || @@ -2463,6 +2485,18 @@ bool change_master(THD* thd, Master_info* mi, bool *master_info_added) strmake(mi->master_log_name, mi->rli.group_master_log_name, sizeof(mi->master_log_name)-1); } + + if (lex_mi->gtid_pos_str.str) + { + if (rpl_global_gtid_slave_state.load(thd, lex_mi->gtid_pos_str.str, + lex_mi->gtid_pos_str.length, true)) + { + my_error(ER_FAILED_GTID_STATE_INIT, MYF(0)); + ret= TRUE; + goto err; + } + } + /* Relay log's IO_CACHE may not be inited, if rli->inited==0 (server was never a slave before). |