Commit 1d357776 authored by unknown's avatar unknown

MDEV-26: Global transaction ID.

When starting slave, check binlog state in addition to mysql.rpl_slave.state.

This allows to switch a previous master to be a slave directly
with MASTER_GTID_POS=AUTO.
parent 0b36233a
......@@ -120,7 +120,7 @@ static MYSQL_BIN_LOG::xid_count_per_binlog *
static bool start_binlog_background_thread();
rpl_binlog_state rpl_global_gtid_binlog_state;
static rpl_binlog_state rpl_global_gtid_binlog_state;
/**
purge logs, master and slave sides both, related error code
......@@ -5488,6 +5488,13 @@ end:
}
int
MYSQL_BIN_LOG::get_most_recent_gtid_list(rpl_gtid **list, uint32 *size)
{
return rpl_global_gtid_binlog_state.get_most_recent_gtid_list(list, size);
}
/**
Write an event to the binary log. If with_annotate != NULL and
*with_annotate = TRUE write also Annotate_rows before the event
......@@ -8176,8 +8183,7 @@ int TC_LOG_BINLOG::open(const char *opt_name)
else
error= read_state_from_file();
/* Pick the next unused seq_no from the loaded/recovered binlog state. */
global_gtid_counter= rpl_global_gtid_binlog_state.seq_no_for_server_id
(global_system_variables.server_id);
global_gtid_counter= rpl_global_gtid_binlog_state.seq_no_from_state();
delete ev;
end_io_cache(&log);
......
......@@ -396,6 +396,7 @@ private:
( ((ulong)(c)>>1) == BINLOG_COOKIE_DUMMY_ID )
class binlog_cache_mngr;
class rpl_gtid;
class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
{
private:
......@@ -773,6 +774,7 @@ public:
bool write_gtid_event(THD *thd, bool standalone, bool is_transactional);
int read_state_from_file();
int write_state_to_file();
int get_most_recent_gtid_list(rpl_gtid **list, uint32 *size);
};
class Log_event_handler
......
This diff is collapsed.
......@@ -2981,7 +2981,7 @@ struct rpl_slave_state
uint32 domain_id;
list_element *grab_list() { list_element *l= list; list= NULL; return l; }
void add (list_element *l)
void add(list_element *l)
{
l->next= list;
list= l;
......@@ -3008,7 +3008,7 @@ struct rpl_slave_state
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);
int tostring(String *dest, rpl_gtid *extra_gtids, uint32 num_extra);
bool is_empty();
void lock() { DBUG_ASSERT(inited); mysql_mutex_lock(&LOCK_slave_state); }
......@@ -3027,10 +3027,21 @@ struct rpl_slave_state
containing a gigen GTID, by simply scanning backwards from the newest
one until a lower seq_no is found in the Gtid_list_log_event at the
start of a binlog for the given domain_id and server_id.
We also remember the last logged GTID for every domain_id. This is used
to know where to start when a master is changed to a slave. As a side
effect, it also allows to skip a hash lookup in the very common case of
logging a new GTID with same server id as last GTID.
*/
struct rpl_binlog_state
{
/* Mapping from (domain_id,server_id) to its GTID. */
struct element {
uint32 domain_id;
HASH hash; /* Containing all server_id for one domain_id */
/* The most recent entry in the hash. */
rpl_gtid *last_gtid;
};
/* Mapping from domain_id to collection of elements. */
HASH hash;
/* Mutex protecting access to the state. */
mysql_mutex_t LOCK_binlog_state;
......@@ -3038,12 +3049,14 @@ struct rpl_binlog_state
rpl_binlog_state();
~rpl_binlog_state();
ulong count() const { return hash.records; }
int update(const struct rpl_gtid *gtid);
void reset();
uint32 seq_no_for_server_id(uint32 server_id);
int update(const struct rpl_gtid *gtid);
uint32 seq_no_from_state();
int write_to_iocache(IO_CACHE *dest);
int read_from_iocache(IO_CACHE *src);
uint32 count();
int get_gtid_list(rpl_gtid *gtid_list, uint32 list_size);
int get_most_recent_gtid_list(rpl_gtid **list, uint32 *size);
};
......
......@@ -1792,10 +1792,29 @@ after_set_capability:
char str_buf[256];
String connect_state(str_buf, sizeof(str_buf), system_charset_info);
connect_state.length(0);
rpl_gtid *binlog_gtid_list= NULL;
uint32 num_binlog_gtids= 0;
if (opt_bin_log)
{
int err= mysql_bin_log.get_most_recent_gtid_list(&binlog_gtid_list,
&num_binlog_gtids);
if (err)
{
err_code= ER_OUTOFMEMORY;
errmsg= "The slave I/O thread stops because a fatal out-of-memory "
"error is encountered when it tries to compute @slave_connect_state.";
sprintf(err_buff, "%s Error: Out of memory", errmsg);
goto err;
}
}
connect_state.append(STRING_WITH_LEN("SET @slave_connect_state='"),
system_charset_info);
rpl_global_gtid_slave_state.tostring(&connect_state);
rpl_global_gtid_slave_state.tostring(&connect_state, binlog_gtid_list,
num_binlog_gtids);
if (binlog_gtid_list)
my_free(binlog_gtid_list);
connect_state.append(STRING_WITH_LEN("'"), system_charset_info);
rc= mysql_real_query(mysql, connect_state.ptr(), connect_state.length());
if (rc)
......
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