summaryrefslogtreecommitdiff
path: root/sql/rpl_gtid.cc
diff options
context:
space:
mode:
authorKristian Nielsen <knielsen@knielsen-hq.org>2017-03-09 15:30:19 +0100
committerKristian Nielsen <knielsen@knielsen-hq.org>2017-04-21 08:00:06 +0200
commit3501a5356e7358c0accfd3465a0c2f66f9b87b70 (patch)
tree7928896cff1d4d45975099e595b1e05ce3aabbc6 /sql/rpl_gtid.cc
parentc995ecbe9834bae31912e00cc98f7c872b63e1fb (diff)
downloadmariadb-git-3501a5356e7358c0accfd3465a0c2f66f9b87b70.tar.gz
MDEV-12179: Per-engine mysql.gtid_slave_pos table
Intermediate commit. When deleting old GTIDs, only pick those GTIDs that were recorded using the same engine. (Currently this is not used, there is only one table/engine active. This is in preparation for extending record_gtid to pick the table with the same engine as the active transaction, if any).
Diffstat (limited to 'sql/rpl_gtid.cc')
-rw-r--r--sql/rpl_gtid.cc83
1 files changed, 56 insertions, 27 deletions
diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc
index 2d12aafdd02..9e6f6ec7009 100644
--- a/sql/rpl_gtid.cc
+++ b/sql/rpl_gtid.cc
@@ -493,11 +493,13 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id,
int err= 0;
bool table_opened= false;
TABLE *table;
- list_element *elist= 0, *next;
+ list_element *delete_list= 0, *next, *cur, **next_ptr_ptr, **best_ptr_ptr;
+ uint64_t best_sub_id;
element *elem;
ulonglong thd_saved_option= thd->variables.option_bits;
Query_tables_list lex_backup;
wait_for_commit* suspended_wfc;
+ void *hton= NULL;
DBUG_ENTER("record_gtid");
*out_hton= NULL;
@@ -553,6 +555,7 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id,
goto end;
table_opened= true;
table= tlist.table;
+ hton= table->s->db_type();
if ((err= gtid_check_rpl_slave_state_table(table)))
goto end;
@@ -588,7 +591,7 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id,
table->file->print_error(err, MYF(0));
goto end;
}
- *out_hton= table->s->db_type();
+ *out_hton= hton;
if(opt_bin_log &&
(err= mysql_bin_log.bump_seq_no_counter_if_needed(gtid->domain_id,
@@ -606,36 +609,62 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id,
err= 1;
goto end;
}
- if ((elist= elem->grab_list()) != NULL)
+
+ /* Now pull out all GTIDs that were recorded in this engine. */
+ delete_list = NULL;
+ next_ptr_ptr= &elem->list;
+ cur= elem->list;
+ best_sub_id= 0;
+ best_ptr_ptr= NULL;
+ while (cur)
{
- /* Delete any old stuff, but keep around the most recent one. */
- list_element *cur= elist;
- uint64 best_sub_id= cur->sub_id;
- list_element **best_ptr_ptr= &elist;
- while ((next= cur->next))
+ list_element *next= cur->next;
+ if (cur->hton == hton)
{
- if (next->sub_id > best_sub_id)
+ /* Belongs to same engine, so move it to the delete list. */
+ cur->next= delete_list;
+ delete_list= cur;
+ if (cur->sub_id > best_sub_id)
{
- best_sub_id= next->sub_id;
+ best_sub_id= cur->sub_id;
+ best_ptr_ptr= &delete_list;
+ }
+ else if (best_ptr_ptr == &delete_list)
best_ptr_ptr= &cur->next;
+ }
+ else
+ {
+ /* Another engine, leave it in the list. */
+ if (cur->sub_id > best_sub_id)
+ {
+ best_sub_id= cur->sub_id;
+ /* Current best is not on the delete list. */
+ best_ptr_ptr= NULL;
}
- cur= next;
+ *next_ptr_ptr= cur;
+ next_ptr_ptr= &cur->next;
}
- /*
- Delete the highest sub_id element from the old list, and put it back as
- the single-element new list.
- */
+ cur= next;
+ }
+ *next_ptr_ptr= NULL;
+ /*
+ If the highest sub_id element is on the delete list, put it back on the
+ original list, to preserve the highest sub_id element in the table for
+ GTID position recovery.
+ */
+ if (best_ptr_ptr)
+ {
cur= *best_ptr_ptr;
*best_ptr_ptr= cur->next;
- cur->next= NULL;
+ cur->next= elem->list;
elem->list= cur;
}
mysql_mutex_unlock(&LOCK_slave_state);
- if (!elist)
+ if (!delete_list)
goto end;
- /* Now delete any already committed rows. */
+ /* Now delete any already committed GTIDs. */
bitmap_set_bit(table->read_set, table->field[0]->field_index);
bitmap_set_bit(table->read_set, table->field[1]->field_index);
@@ -644,7 +673,7 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id,
table->file->print_error(err, MYF(0));
goto end;
}
- while (elist)
+ while (delete_list)
{
uchar key_buffer[4+8];
@@ -654,9 +683,9 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id,
/* `break' does not work inside DBUG_EXECUTE_IF */
goto dbug_break; });
- next= elist->next;
+ next= delete_list->next;
- table->field[1]->store(elist->sub_id, true);
+ table->field[1]->store(delete_list->sub_id, true);
/* domain_id is already set in table->record[0] from write_row() above. */
key_copy(key_buffer, table->record[0], &table->key_info[0], 0, false);
if (table->file->ha_index_read_map(table->record[1], key_buffer,
@@ -670,8 +699,8 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id,
not want to endlessly error on the same element in case of table
corruption or such.
*/
- my_free(elist);
- elist= next;
+ my_free(delete_list);
+ delete_list= next;
if (err)
break;
}
@@ -689,13 +718,13 @@ end:
if (err || (err= ha_commit_trans(thd, FALSE)))
{
/*
- If error, we need to put any remaining elist back into the HASH so we
- can do another delete attempt later.
+ If error, we need to put any remaining delete_list back into the HASH
+ so we can do another delete attempt later.
*/
- if (elist)
+ if (delete_list)
{
mysql_mutex_lock(&LOCK_slave_state);
- put_back_list(gtid->domain_id, elist);
+ put_back_list(gtid->domain_id, delete_list);
mysql_mutex_unlock(&LOCK_slave_state);
}