Commit 03aa4876 authored by unknown's avatar unknown

MDEV-4486: Allow to start old-style replication even if mysql.rpl_slave_state is unavailable

If the mysql.gtid_slave_pos table is not available, we cannot load nor update
the current GTID position persistently. This can happen eg. after an upgrade,
before mysql_upgrade_db is run, or if the table is InnoDB and the server is
restarted without the InnoDB storage engine enabled.

Before, replication always failed to start if the table was unavailable. With
this patch, we try to continue with old-style replication, after suitable
complaints in the error log. In strict mode, or if slave is configured to use
GTID, slave still refuses to start.
parent dbe2c506
......@@ -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
--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
......
......@@ -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);
......
......@@ -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 */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment