diff options
author | unknown <knielsen@knielsen-hq.org> | 2013-06-05 14:32:47 +0200 |
---|---|---|
committer | unknown <knielsen@knielsen-hq.org> | 2013-06-05 14:32:47 +0200 |
commit | 5cb486d159e45b9b8dc4d647b2df2492a286cf4d (patch) | |
tree | 85bdb56bae9cad68033b742092012f0961172745 /sql/rpl_gtid.cc | |
parent | 7ad47ab0e080ca66f8a41de461b036d3bdff25fb (diff) | |
download | mariadb-git-5cb486d159e45b9b8dc4d647b2df2492a286cf4d.tar.gz |
MDEV-26: Global transaction ID.
Fix problems related to reconnect. When we need to reconnect (ie. explict
stop/start of just the IO thread by user, or automatic reconnect due to
loosing network connection with the master), it is a bit complex to correctly
resume at the right point without causing duplicate or missing events in the
relay log. The previous code had multiple problems in this regard.
With this patch, the problem is solved as follows. The IO thread keeps track
(in memory) of which GTID was last queued to the relay log. If it needs to
reconnect, it resumes at that GTID position. It also counts number of events
received within the last, possibly partial, event group, and skips the same
number of events after a reconnect, so that events already enqueued before the
reconnect are not duplicated.
(There is no need to keep any persistent state; whenever we restart slave
threads after both of them being stopped (such as after server restart), we
erase the relay logs and start over from the last GTID applied by SQL thread.
But while the SQL thread is running, this patch is needed to get correct relay
log).
Diffstat (limited to 'sql/rpl_gtid.cc')
-rw-r--r-- | sql/rpl_gtid.cc | 91 |
1 files changed, 66 insertions, 25 deletions
diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc index adaf9aa4e31..d5e9380296e 100644 --- a/sql/rpl_gtid.cc +++ b/sql/rpl_gtid.cc @@ -482,26 +482,10 @@ rpl_slave_state_tostring_helper(String *dest, const rpl_gtid *gtid, bool *first) } -/* - Prepare the current slave state as a string, suitable for sending to the - master to request to receive binlog events starting from that GTID state. - - The state consists of the most recently applied GTID for each domain_id, - ie. the one with the highest sub_id within each domain_id. - - Optinally, extra_gtids is a list of GTIDs from the binlog. This is used when - a server was previously a master and now needs to connect to a new master as - a slave. For each domain_id, if the GTID in the binlog was logged with our - own server_id _and_ has a higher seq_no than what is in the slave state, - then this should be used as the position to start replicating at. This - allows to promote a slave as new master, and connect the old master as a - slave with MASTER_GTID_POS=AUTO. -*/ - int -rpl_slave_state::tostring(String *dest, rpl_gtid *extra_gtids, uint32 num_extra) +rpl_slave_state::iterate(int (*cb)(rpl_gtid *, void *), void *data, + rpl_gtid *extra_gtids, uint32 num_extra) { - bool first= true; uint32 i; HASH gtid_hash; uchar *rec; @@ -555,7 +539,7 @@ rpl_slave_state::tostring(String *dest, rpl_gtid *extra_gtids, uint32 num_extra) } } - if (rpl_slave_state_tostring_helper(dest, &best_gtid, &first)) + if ((res= (*cb)(&best_gtid, data))) { unlock(); goto err; @@ -568,7 +552,7 @@ rpl_slave_state::tostring(String *dest, rpl_gtid *extra_gtids, uint32 num_extra) for (i= 0; i < gtid_hash.records; ++i) { gtid= (rpl_gtid *)my_hash_element(>id_hash, i); - if (rpl_slave_state_tostring_helper(dest, gtid, &first)) + if ((res= (*cb)(gtid, data))) goto err; } @@ -581,6 +565,44 @@ err: } +struct rpl_slave_state_tostring_data { + String *dest; + bool first; +}; +static int +rpl_slave_state_tostring_cb(rpl_gtid *gtid, void *data) +{ + rpl_slave_state_tostring_data *p= (rpl_slave_state_tostring_data *)data; + return rpl_slave_state_tostring_helper(p->dest, gtid, &p->first); +} + + +/* + Prepare the current slave state as a string, suitable for sending to the + master to request to receive binlog events starting from that GTID state. + + The state consists of the most recently applied GTID for each domain_id, + ie. the one with the highest sub_id within each domain_id. + + Optinally, extra_gtids is a list of GTIDs from the binlog. This is used when + a server was previously a master and now needs to connect to a new master as + a slave. For each domain_id, if the GTID in the binlog was logged with our + own server_id _and_ has a higher seq_no than what is in the slave state, + then this should be used as the position to start replicating at. This + allows to promote a slave as new master, and connect the old master as a + slave with MASTER_GTID_POS=AUTO. +*/ +int +rpl_slave_state::tostring(String *dest, rpl_gtid *extra_gtids, uint32 num_extra) +{ + struct rpl_slave_state_tostring_data data; + data.first= true; + data.dest= dest; + + return iterate(rpl_slave_state_tostring_cb, &data, extra_gtids, num_extra); +} + + /* Lookup a domain_id in the current replication slave state. @@ -626,9 +648,6 @@ rpl_slave_state::domain_to_gtid(uint32 domain_id, rpl_gtid *out_gtid) Parse a GTID at the start of a string, and update the pointer to point at the first character after the parsed GTID. - GTID can be in short form with domain_id=0 implied, SERVERID-SEQNO. - Or long form, DOMAINID-SERVERID-SEQNO. - Returns 0 on ok, non-zero on parse error. */ static int @@ -1217,7 +1236,7 @@ slave_connection_state::load(char *slave_request, size_t len) rpl_gtid *gtid; const rpl_gtid *gtid2; - my_hash_reset(&hash); + reset(); p= slave_request; end= slave_request + len; if (p == end) @@ -1270,7 +1289,7 @@ slave_connection_state::load(const rpl_gtid *gtid_list, uint32 count) { uint32 i; - my_hash_reset(&hash); + reset(); for (i= 0; i < count; ++i) if (update(>id_list[i])) return 1; @@ -1278,6 +1297,28 @@ slave_connection_state::load(const rpl_gtid *gtid_list, uint32 count) } +static int +slave_connection_state_load_cb(rpl_gtid *gtid, void *data) +{ + slave_connection_state *state= (slave_connection_state *)data; + return state->update(gtid); +} + + +/* + Same as rpl_slave_state::tostring(), but populates a slave_connection_state + instead. +*/ +int +slave_connection_state::load(rpl_slave_state *state, + rpl_gtid *extra_gtids, uint32 num_extra) +{ + reset(); + return state->iterate(slave_connection_state_load_cb, this, + extra_gtids, num_extra); +} + + rpl_gtid * slave_connection_state::find(uint32 domain_id) { |