[Commits] Rev 3686: MDEV-4650: show variables; ERROR 1946 (HY000): Failed to load replication slave GTID position in http://bazaar.launchpad.net/~maria-captains/maria/10.0

knielsen at knielsen-hq.org knielsen at knielsen-hq.org
Mon Aug 26 13:51:09 EEST 2013


At http://bazaar.launchpad.net/~maria-captains/maria/10.0

------------------------------------------------------------
revno: 3686
revision-id: knielsen at knielsen-hq.org-20130826105109-fuzmdpnn6k93nf0k
parent: knielsen at knielsen-hq.org-20130823120213-pbhsq4zc1h3jwa0i
committer: knielsen at knielsen-hq.org
branch nick: work-10.0-mdev26
timestamp: Mon 2013-08-26 12:51:09 +0200
message:
  MDEV-4650: show variables; ERROR 1946 (HY000): Failed to load replication slave GTID position
  
  The bug was that if mysql.slave_gtid_pos was missing, operations on variables
  gtid_slave_pos, gtid_binlog_pos, and gtid_current_pos would fail, and continue
  to fail even after the table was fixed, until server restart.
  
  Now setting the variables retry loading the table, succeeding if it has been
  restored. And querying the variables when the table is not there acts as if
  the table was there and was empty.
  
  Also, attempt to fix a race in the rpl.rpl_gtid_basic test case.
=== modified file 'mysql-test/suite/rpl/r/rpl_gtid_stop_start.result'
--- a/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result	2013-06-21 19:23:24 +0000
+++ b/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result	2013-08-26 10:51:09 +0000
@@ -155,5 +155,31 @@ SELECT domain_id, COUNT(*) FROM mysql.gt
 domain_id       COUNT(*)
 0       2
 1       2
+*** MDEV-4650: show variables; ERROR 1946 (HY000): Failed to load replication slave GTID position ***
+SET sql_log_bin=0;
+RENAME TABLE mysql.gtid_slave_pos TO mysql.gtid_slave_pos_old;
+SET sql_log_bin=1;
+SHOW VARIABLES;
+SHOW VARIABLES LIKE 'gtid_slave_pos';
+Variable_name   Value
+gtid_slave_pos  
+SET GLOBAL gtid_slave_pos = '0-1-2';
+Got one of the listed errors
+SHOW WARNINGS;
+Level   Code    Message
+Error   1146    Table 'mysql.gtid_slave_pos' doesn't exist
+Error   1946    Failed to load replication slave GTID position from table mysql.gtid_slave_pos
+SET sql_log_bin=0;
+RENAME TABLE mysql.gtid_slave_pos_old TO mysql.gtid_slave_pos;
+CALL mtr.add_suppression("Failed to load slave replication state from table mysql.gtid_slave_pos");
+SET sql_log_bin=1;
+SHOW VARIABLES LIKE 'gtid_slave_pos';
+Variable_name   Value
+gtid_slave_pos  
+SET GLOBAL gtid_slave_pos = '0-1-2';
+SHOW VARIABLES LIKE 'gtid_slave_pos';
+Variable_name   Value
+gtid_slave_pos  0-1-2
+include/start_slave.inc
 DROP TABLE t1;
 include/rpl_end.inc

=== modified file 'mysql-test/suite/rpl/t/rpl_gtid_basic.test'
--- a/mysql-test/suite/rpl/t/rpl_gtid_basic.test	2013-08-23 12:02:13 +0000
+++ b/mysql-test/suite/rpl/t/rpl_gtid_basic.test	2013-08-26 10:51:09 +0000
@@ -191,11 +191,15 @@ SET GLOBAL gtid_binlog_state = @old_stat
 
 CREATE TABLE t1 (a INT PRIMARY KEY);
 INSERT INTO t1 VALUES (1);
---save_master_pos
+--let $master_pos= `SELECT @@GLOBAL.gtid_binlog_pos`
 
 --connection server_2
 --source include/start_slave.inc
---sync_with_master
+# We cannot just use sync_with_master as we've done RESET MASTER, so
+# slave old-style position is wrong.
+# So sync on gtid position instead.
+--let $wait_condition= SELECT @@GLOBAL.gtid_binlog_pos = '$master_pos'
+--source include/wait_condition.inc
 
 SELECT * FROM t1;
 

=== modified file 'mysql-test/suite/rpl/t/rpl_gtid_stop_start.test'
--- a/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test	2013-06-21 19:23:24 +0000
+++ b/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test	2013-08-26 10:51:09 +0000
@@ -273,6 +273,57 @@ INSERT INTO t1 VALUES (13);
 SELECT domain_id, COUNT(*) FROM mysql.gtid_slave_pos GROUP BY domain_id;
 
 
+--echo *** MDEV-4650: show variables; ERROR 1946 (HY000): Failed to load replication slave GTID position ***
+
+--connection server_2
+SET sql_log_bin=0;
+--let $old_pos= `SELECT @@GLOBAL.gtid_slave_pos`
+RENAME TABLE mysql.gtid_slave_pos TO mysql.gtid_slave_pos_old;
+SET sql_log_bin=1;
+
+--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+wait
+EOF
+--shutdown_server 30
+--source include/wait_until_disconnected.inc
+
+# Let the slave mysqld server start again.
+--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect
+restart
+EOF
+
+--enable_reconnect
+--source include/wait_until_connected_again.inc
+
+--disable_result_log
+SHOW VARIABLES;
+--enable_result_log
+SHOW VARIABLES LIKE 'gtid_slave_pos';
+--error ER_CANNOT_LOAD_SLAVE_GTID_STATE,ER_NO_SUCH_TABLE
+SET GLOBAL gtid_slave_pos = '0-1-2';
+SHOW WARNINGS;
+
+# Restore things.
+
+SET sql_log_bin=0;
+RENAME TABLE mysql.gtid_slave_pos_old TO mysql.gtid_slave_pos;
+CALL mtr.add_suppression("Failed to load slave replication state from table mysql.gtid_slave_pos");
+SET sql_log_bin=1;
+
+SHOW VARIABLES LIKE 'gtid_slave_pos';
+SET GLOBAL gtid_slave_pos = '0-1-2';
+SHOW VARIABLES LIKE 'gtid_slave_pos';
+
+# Don't let .result file depend on old state of gtid_slave_pos
+--disable_query_log
+--disable_result_log
+eval SET GLOBAL gtid_slave_pos = '$old_pos';
+--enable_query_log
+--enable_result_log
+
+--source include/start_slave.inc
+
+
 --connection server_1
 DROP TABLE t1;
 

=== modified file 'sql/sys_vars.cc'
--- a/sql/sys_vars.cc	2013-08-23 12:02:13 +0000
+++ b/sql/sys_vars.cc	2013-08-26 10:51:09 +0000
@@ -1282,12 +1282,6 @@ Sys_var_gtid_binlog_pos::global_value_pt
   String str(buf, sizeof(buf), system_charset_info);
   char *p;
 
-  if (!rpl_global_gtid_slave_state.loaded)
-  {
-    my_error(ER_CANNOT_LOAD_SLAVE_GTID_STATE, MYF(0), "mysql",
-             rpl_gtid_slave_state_table_name.str);
-    return NULL;
-  }
   str.length(0);
   if ((opt_bin_log && mysql_bin_log.append_state_pos(&str)) ||
       !(p= thd->strmake(str.ptr(), str.length())))
@@ -1316,7 +1310,17 @@ Sys_var_gtid_current_pos::global_value_p
   char *p;
 
   str.length(0);
-  if (rpl_append_gtid_state(&str, true) ||
+
+  /*
+    If the mysql.rpl_slave_pos table could not be loaded, then we cannot
+    easily automatically try to reload it here - we may be inside a statement
+    that already has tables locked and so opening more tables is problematic.
+
+    But if the table is not loaded (eg. missing mysql_upgrade_db or some such),
+    then the slave state must be empty anyway.
+  */
+  if ((rpl_global_gtid_slave_state.loaded &&
+       rpl_append_gtid_state(&str, true)) ||
       !(p= thd->strmake(str.ptr(), str.length())))
   {
     my_error(ER_OUT_OF_RESOURCES, MYF(0));
@@ -1335,7 +1339,7 @@ Sys_var_gtid_slave_pos::do_check(THD *th
 
   DBUG_ASSERT(var->type == OPT_GLOBAL);
 
-  if (!rpl_global_gtid_slave_state.loaded)
+  if (rpl_load_gtid_slave_state(thd))
   {
     my_error(ER_CANNOT_LOAD_SLAVE_GTID_STATE, MYF(0), "mysql",
              rpl_gtid_slave_state_table_name.str);
@@ -1400,15 +1404,17 @@ Sys_var_gtid_slave_pos::global_value_ptr
   String str;
   char *p;
 
-  if (!rpl_global_gtid_slave_state.loaded)
-  {
-    my_error(ER_CANNOT_LOAD_SLAVE_GTID_STATE, MYF(0), "mysql",
-             rpl_gtid_slave_state_table_name.str);
-    return NULL;
-  }
-
   str.length(0);
-  if (rpl_append_gtid_state(&str, false) ||
+  /*
+    If the mysql.rpl_slave_pos table could not be loaded, then we cannot
+    easily automatically try to reload it here - we may be inside a statement
+    that already has tables locked and so opening more tables is problematic.
+
+    But if the table is not loaded (eg. missing mysql_upgrade_db or some such),
+    then the slave state must be empty anyway.
+  */
+  if ((rpl_global_gtid_slave_state.loaded &&
+       rpl_append_gtid_state(&str, false)) ||
       !(p= thd->strmake(str.ptr(), str.length())))
   {
     my_error(ER_OUT_OF_RESOURCES, MYF(0));



More information about the commits mailing list