summaryrefslogtreecommitdiff
path: root/sql/rpl_gtid.h
diff options
context:
space:
mode:
authorunknown <knielsen@knielsen-hq.org>2014-02-07 19:15:28 +0100
committerunknown <knielsen@knielsen-hq.org>2014-02-07 19:15:28 +0100
commit4e6606acad4ad0ea75dec114ad316e0325efaf02 (patch)
treeabb53cd21ab57261299ec9c96fef4089f7025d1d /sql/rpl_gtid.h
parentce02738d7f2f2688eeec7004dd6a30293d36044f (diff)
downloadmariadb-git-4e6606acad4ad0ea75dec114ad316e0325efaf02.tar.gz
MDEV-4984: Implement MASTER_GTID_WAIT() and @@LAST_GTID.
MASTER_GTID_WAIT() is similar to MASTER_POS_WAIT(), but works with a GTID position rather than an old-style filename/offset. @@LAST_GTID gives the GTID assigned to the last transaction written into the binlog. Together, the two can be used by applications to obtain the GTID of an update on the master, and then do a MASTER_GTID_WAIT() for that position on any read slave where it is important to get results that are caught up with the master at least to the point of the update. The implementation of MASTER_GTID_WAIT() is implemented in a way that tries to minimise the performance impact on the SQL threads, even in the presense of many waiters on single GTID positions (as from @@LAST_GTID).
Diffstat (limited to 'sql/rpl_gtid.h')
-rw-r--r--sql/rpl_gtid.h59
1 files changed, 56 insertions, 3 deletions
diff --git a/sql/rpl_gtid.h b/sql/rpl_gtid.h
index b0bc54900e7..1cf57c45018 100644
--- a/sql/rpl_gtid.h
+++ b/sql/rpl_gtid.h
@@ -16,6 +16,10 @@
#ifndef RPL_GTID_H
#define RPL_GTID_H
+#include "hash.h"
+#include "queues.h"
+
+
/* Definitions for MariaDB global transaction ID (GTID). */
@@ -61,6 +65,15 @@ struct rpl_slave_state
{
struct list_element *list;
uint32 domain_id;
+ /* Highest seq_no seen so far in this domain. */
+ uint64 highest_seq_no;
+ /*
+ If min_wait_seq_no is non-zero, then it is the smallest seq_no in this
+ domain that someone is doing MASTER_GTID_WAIT() on. When we reach this
+ seq_no, we need to signal the waiter on COND_wait_gtid.
+ */
+ uint64 min_wait_seq_no;
+ mysql_cond_t COND_wait_gtid;
list_element *grab_list() { list_element *l= list; list= NULL; return l; }
void add(list_element *l)
@@ -99,9 +112,6 @@ struct rpl_slave_state
bool in_statement);
bool is_empty();
- void lock() { DBUG_ASSERT(inited); mysql_mutex_lock(&LOCK_slave_state); }
- void unlock() { DBUG_ASSERT(inited); mysql_mutex_unlock(&LOCK_slave_state); }
-
element *get_element(uint32 domain_id);
int put_back_list(uint32 domain_id, list_element *list);
@@ -204,6 +214,49 @@ struct slave_connection_state
int get_gtid_list(rpl_gtid *gtid_list, uint32 list_size);
};
+
+/*
+ Structure to keep track of threads waiting in MASTER_GTID_WAIT().
+
+ Since replication is (mostly) single-threaded, we want to minimise the
+ performance impact on that from MASTER_GTID_WAIT(). To achieve this, we
+ are careful to keep the common lock between replication threads and
+ MASTER_GTID_WAIT threads held for as short as possible. We keep only
+ a single thread waiting to be notified by the replication threads; this
+ thread then handles all the (potentially heavy) lifting of dealing with
+ all current waiting threads.
+*/
+
+struct gtid_waiting {
+ /* Elements in the hash, basically a priority queue for each domain. */
+ struct hash_element {
+ QUEUE queue;
+ uint32 domain_id;
+ };
+ /* A priority queue to handle waiters in one domain in seq_no order. */
+ struct queue_element {
+ uint64 wait_seq_no;
+ THD *thd;
+ int queue_idx;
+ enum { DONE, TAKEOVER } wakeup_reason;
+ };
+
+ mysql_mutex_t LOCK_gtid_waiting;
+ HASH hash;
+
+ void init();
+ void destroy();
+ hash_element *get_entry(uint32 domain_id);
+ int wait_for_pos(THD *thd, String *gtid_str, longlong timeout_us);
+ void promote_new_waiter(gtid_waiting::hash_element *he);
+ int wait_for_gtid(THD *thd, rpl_gtid *wait_gtid, struct timespec *wait_until);
+ void process_wait_hash(uint64 wakeup_seq_no, gtid_waiting::hash_element *he);
+ hash_element *register_in_wait_hash(THD *thd, rpl_gtid *wait_gtid,
+ queue_element *elem);
+ void remove_from_wait_hash(hash_element *e, queue_element *elem);
+};
+
+
extern bool rpl_slave_state_tostring_helper(String *dest, const rpl_gtid *gtid,
bool *first);
extern int gtid_check_rpl_slave_state_table(TABLE *table);