[Commits] d97142d: MDEV-12179: Per-engine mysql.gtid_slave_pos table

Kristian Nielsen knielsen at knielsen-hq.org
Thu Mar 9 16:47:27 EET 2017


revision-id: d97142d385a225aab37b7643706fef4284377f68 (mariadb-10.1.21-5-gd97142d)
parent(s): 15e5c91276ee8f6a0ab3e0543d9292786aba88cb
author: Kristian Nielsen
committer: Kristian Nielsen
timestamp: 2017-03-09 15:30:19 +0100
message:

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).

---
 sql/rpl_gtid.cc | 83 ++++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 56 insertions(+), 27 deletions(-)

diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc
index d3057fd..d7d7148 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 @@ 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);
       }
 


More information about the commits mailing list