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:
@@ -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);
|
||||
};
|
||||
|
Reference in New Issue
Block a user