Skip to content

Commit

Permalink
MDEV-12179: Per-engine mysql.gtid_slave_pos table
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
knielsen committed Apr 21, 2017
1 parent c995ecb commit 3501a53
Showing 1 changed file with 56 additions and 27 deletions.
83 changes: 56 additions & 27 deletions sql/rpl_gtid.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand All @@ -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);

Expand All @@ -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];

Expand All @@ -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,
Expand All @@ -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;
}
Expand All @@ -689,13 +718,13 @@ IF_DBUG(dbug_break:, )
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);
}

Expand Down

0 comments on commit 3501a53

Please sign in to comment.