diff --git a/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result b/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result index b524ab17c23..708b553e76d 100644 --- a/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result +++ b/mysql-test/suite/rpl/r/rpl_gtid_stop_start.result @@ -59,6 +59,57 @@ OK SELECT IF(@current_pos1=@current_pos2, "OK", CONCAT(@current_pos1, " != ", @current_pos2)); IF(@current_pos1=@current_pos2, "OK", CONCAT(@current_pos1, " != ", @current_pos2)) OK +INSERT INTO t1 VALUES (6); +include/start_slave.inc +SELECT * FROM t1 ORDER BY a; +a +1 +2 +3 +4 +5 +6 +*** MDEV-4486: Allow to start old-style replication even if mysql.gtid_slave_pos is unavailable +include/stop_slave.inc +CHANGE MASTER TO master_use_gtid= no; +include/start_slave.inc +INSERT INTO t1 VALUES (7); +SELECT * FROM t1 ORDER BY a; +a +1 +2 +3 +4 +5 +6 +7 +include/stop_slave.inc +SET sql_log_bin= 0; +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +SET sql_log_bin= 1; +SELECT * FROM mysql.gtid_slave_pos; +ERROR 42000: Unknown storage engine 'InnoDB' +SET sql_log_bin=0; +call mtr.add_suppression("Failed to load slave replication state from table"); +call mtr.add_suppression("Unable to load replication GTID slave state"); +SET sql_log_bin=1; +include/start_slave.inc +Warnings: +Error 1286 Unknown storage engine 'InnoDB' +INSERT INTO t1 VALUES (8); +SELECT * FROM t1 ORDER BY a; +a +1 +2 +3 +4 +5 +6 +7 +8 +SET sql_log_bin= 0; +ALTER TABLE mysql.gtid_slave_pos ENGINE=MyISAM; +SET sql_log_bin= 1; include/start_slave.inc DROP TABLE t1; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test b/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test index cc1da6b3c85..05cb078558d 100644 --- a/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test +++ b/mysql-test/suite/rpl/t/rpl_gtid_stop_start.test @@ -1,5 +1,6 @@ --let $rpl_topology=1->2 --source include/rpl_init.inc +--source include/have_innodb.inc --echo *** Test normal shutdown/restart of slave server configured as a GTID slave. *** @@ -116,6 +117,80 @@ SET @slave_pos2= @@GLOBAL.gtid_slave_pos; SET @current_pos2= @@GLOBAL.gtid_current_pos; SELECT IF(@slave_pos1=@slave_pos2, "OK", CONCAT(@slave_pos1, " != ", @slave_pos2)); SELECT IF(@current_pos1=@current_pos2, "OK", CONCAT(@current_pos1, " != ", @current_pos2)); + +--connection server_1 +INSERT INTO t1 VALUES (6); +--save_master_pos + +--connection server_2 +--source include/start_slave.inc +--sync_with_master +SELECT * FROM t1 ORDER BY a; + + +--echo *** MDEV-4486: Allow to start old-style replication even if mysql.gtid_slave_pos is unavailable + +--connection server_2 +--source include/stop_slave.inc +CHANGE MASTER TO master_use_gtid= no; +--source include/start_slave.inc + +--connection server_1 +INSERT INTO t1 VALUES (7); +--save_master_pos + +--connection server_2 +--sync_with_master +SELECT * FROM t1 ORDER BY a; +--source include/stop_slave.inc + +SET sql_log_bin= 0; +ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB; +SET sql_log_bin= 1; + +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +wait +EOF +--shutdown_server 30 +--source include/wait_until_disconnected.inc + +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +restart: --skip-slave-start=1 --skip-innodb +EOF +--enable_reconnect +--source include/wait_until_connected_again.inc + +--error ER_UNKNOWN_STORAGE_ENGINE +SELECT * FROM mysql.gtid_slave_pos; +SET sql_log_bin=0; +call mtr.add_suppression("Failed to load slave replication state from table"); +call mtr.add_suppression("Unable to load replication GTID slave state"); +SET sql_log_bin=1; + +--source include/start_slave.inc +--connection server_1 +INSERT INTO t1 VALUES (8); +--save_master_pos + +--connection server_2 +--sync_with_master +SELECT * FROM t1 ORDER BY a; + +# Put things back as they were. +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +wait +EOF +--shutdown_server 30 +--source include/wait_until_disconnected.inc + +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +restart: +EOF +--enable_reconnect +--source include/wait_until_connected_again.inc +SET sql_log_bin= 0; +ALTER TABLE mysql.gtid_slave_pos ENGINE=MyISAM; +SET sql_log_bin= 1; --source include/start_slave.inc diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc index d5e9380296e..71b18e64842 100644 --- a/sql/rpl_gtid.cc +++ b/sql/rpl_gtid.cc @@ -311,6 +311,18 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id, ulonglong thd_saved_option= thd->variables.option_bits; Query_tables_list lex_backup; + if (unlikely(!loaded)) + { + /* + Probably the mysql.gtid_slave_pos table is missing (eg. upgrade) or + corrupt. + + We already complained loudly about this, but we can try to continue + until the DBA fixes it. + */ + return 0; + } + if (!in_statement) mysql_reset_thd_for_next_command(thd, 0); diff --git a/sql/slave.cc b/sql/slave.cc index ac6feb16162..8cb13205f29 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -3536,7 +3536,13 @@ pthread_handler_t handle_slave_io(void *arg) mi->report(ERROR_LEVEL, thd->stmt_da->sql_errno(), "Unable to load replication GTID slave state from mysql.%s: %s", rpl_gtid_slave_state_table_name.str, thd->stmt_da->message()); - goto err; + /* + If we are using old-style replication, we can continue, even though we + then will not be able to record the GTIDs we receive. But if using GTID, + we must give up. + */ + if (mi->using_gtid != Master_info::USE_GTID_NO || opt_gtid_strict_mode) + goto err; } @@ -4141,7 +4147,13 @@ log '%s' at position %s, relay log '%s' position: %s%s", RPL_LOG_NAME, rli->report(ERROR_LEVEL, thd->stmt_da->sql_errno(), "Unable to load replication GTID slave state from mysql.%s: %s", rpl_gtid_slave_state_table_name.str, thd->stmt_da->message()); - goto err; + /* + If we are using old-style replication, we can continue, even though we + then will not be able to record the GTIDs we receive. But if using GTID, + we must give up. + */ + if (mi->using_gtid != Master_info::USE_GTID_NO || opt_gtid_strict_mode) + goto err; } /* execute init_slave variable */