1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

MDEV-12179: Per-engine mysql.gtid_slave_pos table

Intermediate commit.

This commit implements that record_gtid() selects a gtid_slave_posXXX table
with a storage engine already in use by current transaction, if any.

The default table mysql.gtid_slave_pos is used if no match can be found on
storage engine, or for GTID position updates with no specific storage
engine.

Table discovery of mysql.gtid_slave_pos* happens on initial GTID state load
as well as on every START SLAVE. Some effort is made to make this possible
without additional locking. New tables are added using lock-free atomics.
Removing tables requires stopping all slaves first. A warning is given in
the error log when a table is removed but a non-stopped slave still has a
reference to it.

If multiple mysql.gtid_slave_posXXX tables with same storage engine exist,
one is chosen arbitrarily to be used, with a warning in the error log. GTID
data from all tables is still read, but only one among redundant tables with
same storage engine will be updated.
This commit is contained in:
Kristian Nielsen
2017-03-14 12:54:10 +01:00
parent 3501a5356e
commit 6a84473c28
8 changed files with 663 additions and 34 deletions

View File

@@ -177,7 +177,27 @@ struct rpl_slave_state
DYNAMIC_ARRAY gtid_sort_array;
uint64 last_sub_id;
/*
List of tables available for durably storing the slave GTID position.
Accesses to this table is protected by LOCK_slave_state. However for
efficiency, there is also a provision for read access to it from a running
slave without lock.
An element can be added at the head of a list by storing the new
gtid_pos_tables pointer atomically with release semantics, to ensure that
the next pointer of the new element is visible to readers of the new list.
Other changes (like deleting or replacing elements) must happen only while
all SQL driver threads are stopped. LOCK_slave_state must be held in any
case.
The list can be read without lock by an SQL driver thread or worker thread
by reading the gtid_pos_tables pointer atomically with acquire semantics,
to ensure that it will see the correct next pointer of a new head element.
*/
struct gtid_pos_table *gtid_pos_tables;
/* The default entry in gtid_pos_tables, mysql.gtid_slave_pos. */
struct gtid_pos_table *default_gtid_pos_table;
bool loaded;
rpl_slave_state();
@@ -188,6 +208,7 @@ struct rpl_slave_state
int update(uint32 domain_id, uint32 server_id, uint64 sub_id,
uint64 seq_no, void *hton, rpl_group_info *rgi);
int truncate_state_table(THD *thd);
void select_gtid_pos_table(THD *thd, LEX_STRING *out_tablename);
int record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id,
bool in_transaction, bool in_statement, void **out_hton);
uint64 next_sub_id(uint32 domain_id);
@@ -208,7 +229,9 @@ struct rpl_slave_state
int record_and_update_gtid(THD *thd, struct rpl_group_info *rgi);
int check_duplicate_gtid(rpl_gtid *gtid, rpl_group_info *rgi);
void release_domain_owner(rpl_group_info *rgi);
void set_gtid_pos_tables_list(struct gtid_pos_table *new_list);
void set_gtid_pos_tables_list(gtid_pos_table *new_list,
gtid_pos_table *default_entry);
void add_gtid_pos_table(gtid_pos_table *entry);
struct gtid_pos_table *alloc_gtid_pos_table(LEX_STRING *table_name, void *hton);
void free_gtid_pos_tables(struct gtid_pos_table *list);
};