summaryrefslogtreecommitdiff
path: root/sql/rpl_rli.cc
diff options
context:
space:
mode:
authorKristian Nielsen <knielsen@knielsen-hq.org>2018-10-14 20:41:49 +0200
committerKristian Nielsen <knielsen@knielsen-hq.org>2018-12-07 07:10:40 +0100
commit34f11b06e6aa5e8d4e648c04b5a4049179b66cfd (patch)
tree6731ebc08eb861b1d80eaf45ffbe7734b9afa104 /sql/rpl_rli.cc
parent24a45d3bd735f0ab09c1b6d313015022e08c8b39 (diff)
downloadmariadb-git-34f11b06e6aa5e8d4e648c04b5a4049179b66cfd.tar.gz
Move deletion of old GTID rows to slave background thread
This patch changes how old rows in mysql.gtid_slave_pos* tables are deleted. Instead of doing it as part of every replicated transaction in record_gtid(), it is done periodically (every @@gtid_cleanup_batch_size transaction) in the slave background thread. This removes the deletion step from the replication process in SQL or worker threads, which could speed up replication with many small transactions. It also decreases contention on the global mutex LOCK_slave_state. And it simplifies the logic, eg. when a replicated transaction fails after having deleted old rows. With this patch, the deletion of old GTID rows happens asynchroneously and slightly non-deterministic. Thus the number of old rows in mysql.gtid_slave_pos can temporarily exceed @@gtid_cleanup_batch_size. But all old rows will be deleted eventually after sufficiently many new GTIDs have been replicated.
Diffstat (limited to 'sql/rpl_rli.cc')
-rw-r--r--sql/rpl_rli.cc87
1 files changed, 8 insertions, 79 deletions
diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc
index b275ad884bd..2d91620c898 100644
--- a/sql/rpl_rli.cc
+++ b/sql/rpl_rli.cc
@@ -1820,6 +1820,7 @@ rpl_load_gtid_slave_state(THD *thd)
int err= 0;
uint32 i;
load_gtid_state_cb_data cb_data;
+ rpl_slave_state::list_element *old_gtids_list;
DBUG_ENTER("rpl_load_gtid_slave_state");
mysql_mutex_lock(&rpl_global_gtid_slave_state->LOCK_slave_state);
@@ -1905,6 +1906,13 @@ rpl_load_gtid_slave_state(THD *thd)
rpl_global_gtid_slave_state->loaded= true;
mysql_mutex_unlock(&rpl_global_gtid_slave_state->LOCK_slave_state);
+ /* Clear out no longer needed elements now. */
+ old_gtids_list=
+ rpl_global_gtid_slave_state->gtid_grab_pending_delete_list();
+ rpl_global_gtid_slave_state->gtid_delete_pending(thd, &old_gtids_list);
+ if (old_gtids_list)
+ rpl_global_gtid_slave_state->put_back_list(old_gtids_list);
+
end:
if (array_inited)
delete_dynamic(&array);
@@ -2086,7 +2094,6 @@ rpl_group_info::reinit(Relay_log_info *rli)
long_find_row_note_printed= false;
did_mark_start_commit= false;
gtid_ev_flags2= 0;
- pending_gtid_delete_list= NULL;
last_master_timestamp = 0;
gtid_ignore_duplicate_state= GTID_DUPLICATE_NULL;
speculation= SPECULATE_NO;
@@ -2217,12 +2224,6 @@ void rpl_group_info::cleanup_context(THD *thd, bool error)
erroneously update the GTID position.
*/
gtid_pending= false;
-
- /*
- Rollback will have undone any deletions of old rows we might have made
- in mysql.gtid_slave_pos. Put those rows back on the list to be deleted.
- */
- pending_gtid_deletes_put_back();
}
m_table_map.clear_tables();
slave_close_thread_tables(thd);
@@ -2448,78 +2449,6 @@ rpl_group_info::unmark_start_commit()
}
-/*
- When record_gtid() has deleted any old rows from the table
- mysql.gtid_slave_pos as part of a replicated transaction, save the list of
- rows deleted here.
-
- If later the transaction fails (eg. optimistic parallel replication), the
- deletes will be undone when the transaction is rolled back. Then we can
- put back the list of rows into the rpl_global_gtid_slave_state, so that
- we can re-do the deletes and avoid accumulating old rows in the table.
-*/
-void
-rpl_group_info::pending_gtid_deletes_save(uint32 domain_id,
- rpl_slave_state::list_element *list)
-{
- /*
- We should never get to a state where we try to save a new pending list of
- gtid deletes while we still have an old one. But make sure we handle it
- anyway just in case, so we avoid leaving stray entries in the
- mysql.gtid_slave_pos table.
- */
- DBUG_ASSERT(!pending_gtid_delete_list);
- if (unlikely(pending_gtid_delete_list))
- pending_gtid_deletes_put_back();
-
- pending_gtid_delete_list= list;
- pending_gtid_delete_list_domain= domain_id;
-}
-
-
-/*
- Take the list recorded by pending_gtid_deletes_save() and put it back into
- rpl_global_gtid_slave_state. This is needed if deletion of the rows was
- rolled back due to transaction failure.
-*/
-void
-rpl_group_info::pending_gtid_deletes_put_back()
-{
- if (pending_gtid_delete_list)
- {
- rpl_global_gtid_slave_state->put_back_list(pending_gtid_delete_list_domain,
- pending_gtid_delete_list);
- pending_gtid_delete_list= NULL;
- }
-}
-
-
-/*
- Free the list recorded by pending_gtid_deletes_save(). Done when the deletes
- in the list have been permanently committed.
-*/
-void
-rpl_group_info::pending_gtid_deletes_clear()
-{
- pending_gtid_deletes_free(pending_gtid_delete_list);
- pending_gtid_delete_list= NULL;
-}
-
-
-void
-rpl_group_info::pending_gtid_deletes_free(rpl_slave_state::list_element *list)
-{
- rpl_slave_state::list_element *next;
-
- while (list)
- {
- next= list->next;
- my_free(list);
- list= next;
- }
-}
-
-
rpl_sql_thread_info::rpl_sql_thread_info(Rpl_filter *filter)
: rpl_filter(filter)
{