From: Andrei <andrei.el...@mariadb.com>

When mysqldump run on mysql system database it generates inserts sql commands
into mysql.gtid_slave_pos. After running the backup script those
inserts did not produce an expected gtid state on slave.
In particular the maximum of mysql.gtid_slave_pos.sub_id did not make
into
      rpl_global_gtid_slave_state.last_sub_id
a memory object that the table persists.
And that was regardless of whether --gtid option in or out.
Later when the backup recipient server starts as slave in *non-gtid*
mode this desychronization may lead to a duplicate key error.

This effect is corrected for --gtid mode mysqldump/mariadb-dump only
as the following.
The fixes ensure the insert block of the dump script is followed
with a "summing-up" SET @global.gtid_slave_pos assignment.
To address MDEV-34615 the assignment makes sure a possibly
pre-existing gtid state (e.g reflecting another domain) remains as a
sub-state upon the dump installation.
A new test provides a how-to-reproduce mode as well.

For the implemenation part, note a deferred print-out of SET-gtid_slave_pos
and associated comments is prefered over relocating of the entire blocks
   if (opt_master,slave_data && do_show_master,slave_status) ...
because of compatiblity concern. Namely an error inside
    do_show_*()
is handled in the new code the same way, as early, as before.
---
 client/mysqldump.c | 53 +++++++++++++++++++++++++++++++++++-----------
 1 file changed, 41 insertions(+), 12 deletions(-)

diff --git a/client/mysqldump.c b/client/mysqldump.c
index 1c9d92d6e09..0be890e2528 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -5985,8 +5985,13 @@ static int dump_selected_tables(char *db, char 
**table_names, int tables)
 } /* dump_selected_tables */
 
 
+const char fmt_gtid_pos[] =  "%sSET GLOBAL gtid_slave_pos=concat('%s', "
+  "if(length(@@global.gtid_slave_pos) = 0, '', ','), "
+  "@@global.gtid_slave_pos);\n";
+
 static int do_show_master_status(MYSQL *mysql_con, int consistent_binlog_pos,
-                                 int have_mariadb_gtid, int use_gtid)
+                                 int have_mariadb_gtid, int use_gtid,
+                                 char *set_gtid_pos)
 {
   MYSQL_ROW row;
   MYSQL_RES *UNINIT_VAR(master);
@@ -6054,8 +6059,11 @@ static int do_show_master_status(MYSQL *mysql_con, int 
consistent_binlog_pos,
       fprintf(md_result_file,
               "%sCHANGE MASTER TO MASTER_USE_GTID=slave_pos;\n",
               comment_prefix);
-    fprintf(md_result_file,
-            "%sSET GLOBAL gtid_slave_pos='%s';\n",
+    /*
+      Defer print of SET gtid_slave_pos until after its placeholder
+      table is guaranteed to have been dumped.
+    */
+    sprintf(set_gtid_pos, fmt_gtid_pos,
             (!use_gtid ? "-- " : comment_prefix), gtid_pos);
   }
 
@@ -6140,8 +6148,8 @@ static int add_slave_statements(void)
   return(0);
 }
 
-static int do_show_slave_status(MYSQL *mysql_con, int use_gtid,
-                                int have_mariadb_gtid)
+static int do_show_slave_status(MYSQL *mysql_con, int have_mariadb_gtid,
+                                int use_gtid, char* set_gtid_pos)
 {
   MYSQL_RES *UNINIT_VAR(slave);
   MYSQL_ROW row;
@@ -6181,10 +6189,8 @@ static int do_show_slave_status(MYSQL *mysql_con, int 
use_gtid,
       mysql_free_result(slave);
       return 1;
     }
-    print_comment(md_result_file, 0,
-                  "-- GTID position to start replication:\n");
-    fprintf(md_result_file, "%sSET GLOBAL gtid_slave_pos='%s';\n",
-            gtid_comment_prefix, gtid_pos);
+    /* similarly to do_show_master_status */
+    sprintf(set_gtid_pos, fmt_gtid_pos, gtid_comment_prefix, gtid_pos);
   }
   if (use_gtid)
     print_comment(md_result_file, 0,
@@ -6905,6 +6911,19 @@ static void dynstr_realloc_checked(DYNAMIC_STRING *str, 
ulong additional_size)
     die(EX_MYSQLERR, DYNAMIC_STR_ERROR_MSG);
 }
 
+/**
+  Print earlier prepared SET to @@global.gtid_slave_pos.
+
+  @param set_gtid_pos[in]  formatted sql set statement
+**/
+static void do_print_set_gtid_slave_pos(const char *set_gtid_pos)
+{
+  DBUG_ASSERT(opt_master_data || opt_slave_data);
+  if (opt_slave_data)
+    print_comment(md_result_file, 0,
+                  "-- GTID position to start replication:\n");
+  fprintf(md_result_file, "%s", set_gtid_pos);
+}
 
 int main(int argc, char **argv)
 {
@@ -6913,6 +6932,11 @@ int main(int argc, char **argv)
   int exit_code;
   int consistent_binlog_pos= 0;
   int have_mariadb_gtid= 0;
+  /*
+    to hold SET @@global.gtid_slave_pos which is deferred to print
+    until the function epilogue.
+  */
+  char set_gtid_pos[3 + sizeof(fmt_gtid_pos) + MAX_GTID_LENGTH]= {0};
   MY_INIT(argv[0]);
 
   sf_leaking_memory=1; /* don't report memory leaks on early exits */
@@ -7016,10 +7040,12 @@ int main(int argc, char **argv)
     goto err;
 
   if (opt_master_data && do_show_master_status(mysql, consistent_binlog_pos,
-                                               have_mariadb_gtid, 
opt_use_gtid))
+                                               have_mariadb_gtid,
+                                               opt_use_gtid, set_gtid_pos))
     goto err;
-  if (opt_slave_data && do_show_slave_status(mysql, opt_use_gtid,
-                                             have_mariadb_gtid))
+  if (opt_slave_data && do_show_slave_status(mysql,
+                                             have_mariadb_gtid,
+                                             opt_use_gtid, set_gtid_pos))
     goto err;
   if (opt_single_transaction && do_unlock_tables(mysql)) /* unlock but no 
commit! */
     goto err;
@@ -7087,6 +7113,9 @@ int main(int argc, char **argv)
   if (opt_system & OPT_SYSTEM_TIMEZONES)
     dump_all_timezones();
 
+  if ((opt_master_data || opt_slave_data) && set_gtid_pos[0])
+    do_print_set_gtid_slave_pos(set_gtid_pos);
+
   /* add 'START SLAVE' to end of dump */
   if (opt_slave_apply && add_slave_statements())
     goto err;
-- 
2.39.2

_______________________________________________
commits mailing list -- commits@lists.mariadb.org
To unsubscribe send an email to commits-le...@lists.mariadb.org

Reply via email to