MXS-2047 Create test that reveals problem
If * BLR replicates from a node in a Galera cluster and * writes are made to all nodes in that cluster, then * if a slave to BLR is stopped when it has received an event originating in a node different than the one BLR is replicating from the subsequent (re)starting of the slave will fail because BLR looks for the last event from a file whose path contains the server id of the node where the event originates, although it should look for it in the file whose path contains the server id of the node from which BLR replicates.
This commit is contained in:
parent
6e4556849c
commit
c105a71317
@ -1068,5 +1068,8 @@ add_test_executable(mxs1113_schemarouter_ps.cpp mxs1113_schemarouter_ps mxs1113_
|
||||
# https://jira.mariadb.org/browse/MXS-2037
|
||||
add_test_executable(mxs2037_namedserver_wildcards.cpp mxs2037_namedserver_wildcards mxs2037_namedserver_wildcards LABELS namedserverfilter LIGHT REPL_BACKEND)
|
||||
|
||||
# MXS-2047: BLR must store full path of events
|
||||
# https://jira.mariadb.org/browse/MXS-2047
|
||||
add_test_executable(mxs2047_blr_gtid_path.cpp mxs2047_blr_gtid_path mxs2047_blr_gtid_path LABELS binlogrouter GALERA_BACKEND)
|
||||
|
||||
configure_file(templates.h.in ${CMAKE_CURRENT_BINARY_DIR}/templates.h @ONLY)
|
||||
|
@ -0,0 +1,26 @@
|
||||
[BLR]
|
||||
type=service
|
||||
router=binlogrouter
|
||||
user=repl
|
||||
password=repl
|
||||
version_string=5.6.15-log
|
||||
master_id=5
|
||||
server_id=4711
|
||||
mariadb10_master_gtid=On
|
||||
|
||||
[BLR-Listener]
|
||||
type=listener
|
||||
service=BLR
|
||||
protocol=MariaDBClient
|
||||
port=5306
|
||||
|
||||
[CLI]
|
||||
type=service
|
||||
router=cli
|
||||
|
||||
[CLI Listener]
|
||||
type=listener
|
||||
service=CLI
|
||||
protocol=maxscaled
|
||||
#address=localhost
|
||||
socket=default
|
293
maxscale-system-test/mxs2047_blr_gtid_path.cpp
Normal file
293
maxscale-system-test/mxs2047_blr_gtid_path.cpp
Normal file
@ -0,0 +1,293 @@
|
||||
/*
|
||||
* Copyright (c) 2016 MariaDB Corporation Ab
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file and at www.mariadb.com/bsl11.
|
||||
*
|
||||
* Change Date: 2022-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2 or later of the General
|
||||
* Public License.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
#include <maxbase/assert.h>
|
||||
#include <maxbase/log.hh>
|
||||
#include "testconnections.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// The amount of time slept between various operations that are
|
||||
// expected to take some time before becoming visible.
|
||||
|
||||
const int REPLICATION_SLEEP = 5; // Seconds
|
||||
|
||||
string get_gtid_current_pos(TestConnections& test, MYSQL* pMysql)
|
||||
{
|
||||
std::vector<string> row = get_row(pMysql, "SELECT @@gtid_current_pos");
|
||||
|
||||
test.expect(row.size() == 1, "Did not get @@gtid_current_pos");
|
||||
|
||||
return row.empty() ? "" : row[0];
|
||||
}
|
||||
|
||||
// Setup BLR to replicate from galera_000.
|
||||
bool setup_blr(TestConnections& test, const string& gtid, const char* zHost, int port)
|
||||
{
|
||||
test.tprintf("Connecting to BLR at %s:%d", zHost, port);
|
||||
|
||||
MYSQL* pMysql = open_conn_no_db(port, zHost, "repl", "repl");
|
||||
test.expect(pMysql, "Could not open connection to %s.", zHost);
|
||||
|
||||
test.try_query(pMysql, "STOP SLAVE");
|
||||
test.try_query(pMysql, "SET @@global.gtid_slave_pos='%s'", gtid.c_str());
|
||||
|
||||
mxb_assert(test.galera);
|
||||
Mariadb_nodes& gc = *test.galera;
|
||||
|
||||
stringstream ss;
|
||||
|
||||
ss << "CHANGE MASTER ";
|
||||
ss << "TO MASTER_HOST='" << gc.IP[0] << "', ";
|
||||
ss << "MASTER_PORT=" << gc.port[0] << ", ";
|
||||
ss << "MASTER_USER='repl', MASTER_PASSWORD='repl', MASTER_USE_GTID=Slave_pos";
|
||||
|
||||
string stmt = ss.str();
|
||||
|
||||
cout << stmt << endl;
|
||||
|
||||
test.try_query(pMysql, "%s", stmt.c_str());
|
||||
test.try_query(pMysql, "START SLAVE");
|
||||
|
||||
mysql_close(pMysql);
|
||||
|
||||
return test.global_result == 0;
|
||||
}
|
||||
|
||||
// Setup slave to replicate from BLR.
|
||||
bool setup_slave(TestConnections& test,
|
||||
const string& gtid,
|
||||
MYSQL* pSlave,
|
||||
const char* zMaxscale_host,
|
||||
int maxscale_port)
|
||||
{
|
||||
test.try_query(pSlave, "SET GLOBAL server_id=54"); // Remove this when galera/ms server ids are distinct
|
||||
test.try_query(pSlave, "STOP SLAVE");
|
||||
test.try_query(pSlave, "RESET SLAVE");
|
||||
test.try_query(pSlave, "DROP TABLE IF EXISTS test.MXS2011");
|
||||
test.try_query(pSlave, "SET @@global.gtid_slave_pos='%s'", gtid.c_str());
|
||||
|
||||
stringstream ss;
|
||||
|
||||
ss << "CHANGE MASTER TO ";
|
||||
ss << "MASTER_HOST='" << zMaxscale_host << "', ";
|
||||
ss << "MASTER_PORT=" << maxscale_port << ", ";
|
||||
ss << "MASTER_USER='repl', MASTER_PASSWORD='repl', MASTER_USE_GTID=Slave_pos";
|
||||
|
||||
string stmt = ss.str();
|
||||
|
||||
cout << stmt << endl;
|
||||
|
||||
test.try_query(pSlave, "%s", stmt.c_str());
|
||||
test.try_query(pSlave, "START SLAVE");
|
||||
|
||||
return test.global_result == 0;
|
||||
}
|
||||
|
||||
bool setup_schema(TestConnections& test, MYSQL* pServer)
|
||||
{
|
||||
test.try_query(pServer, "DROP TABLE IF EXISTS test.MXS2011");
|
||||
test.try_query(pServer, "CREATE TABLE test.MXS2011 (i INT)");
|
||||
|
||||
return test.global_result == 0;
|
||||
}
|
||||
|
||||
unsigned count = 0;
|
||||
|
||||
void insert(TestConnections& test, MYSQL* pMaster)
|
||||
{
|
||||
stringstream ss;
|
||||
ss << "INSERT INTO test.MXS2011 VALUES (" << ++count << ")";
|
||||
|
||||
string stmt = ss.str();
|
||||
|
||||
cout << stmt.c_str() << endl;
|
||||
|
||||
test.try_query(pMaster, "%s", stmt.c_str());
|
||||
}
|
||||
|
||||
void select(TestConnections& test, MYSQL* pSlave)
|
||||
{
|
||||
my_ulonglong nRows;
|
||||
unsigned long long nResult_sets;
|
||||
|
||||
int rc = execute_query_num_of_rows(pSlave, "SELECT * FROM test.MXS2011", &nRows, &nResult_sets);
|
||||
test.expect(rc == 0, "Execution of SELECT failed.");
|
||||
|
||||
if (rc == 0)
|
||||
{
|
||||
mxb_assert(nResult_sets == 1);
|
||||
|
||||
test.expect(nRows == count, "Expected %d rows, got %d.", count, (int)nRows);
|
||||
}
|
||||
}
|
||||
|
||||
bool insert_select(TestConnections& test, MYSQL* pSlave, MYSQL* pMaster)
|
||||
{
|
||||
insert(test, pMaster);
|
||||
sleep(REPLICATION_SLEEP); // To ensure that the insert reaches the slave.
|
||||
select(test, pSlave);
|
||||
|
||||
return test.global_result == 0;
|
||||
}
|
||||
|
||||
bool insert_select(TestConnections& test, MYSQL* pSlave)
|
||||
{
|
||||
Mariadb_nodes& gc = *test.galera;
|
||||
|
||||
for (int i = 0; i < gc.N; ++i)
|
||||
{
|
||||
MYSQL* pMaster = gc.nodes[i];
|
||||
|
||||
insert_select(test, pSlave, pMaster);
|
||||
}
|
||||
|
||||
return test.global_result == 0;
|
||||
}
|
||||
|
||||
void reset_galera(TestConnections& test)
|
||||
{
|
||||
Mariadb_nodes& gc = *test.galera;
|
||||
|
||||
for (int i = 0; i < gc.N; ++i)
|
||||
{
|
||||
test.try_query(gc.nodes[i], "RESET MASTER");
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure log_slave_updates is on.
|
||||
void setup_galera(TestConnections& test)
|
||||
{
|
||||
Mariadb_nodes& gc = *test.galera;
|
||||
|
||||
for (int i = 0; i < gc.N; ++i)
|
||||
{
|
||||
gc.stash_server_settings(i);
|
||||
gc.add_server_setting(i, "log_slave_updates=1");
|
||||
}
|
||||
}
|
||||
|
||||
// Restore log_slave_updates as it was.
|
||||
void restore_galera(TestConnections& test)
|
||||
{
|
||||
Mariadb_nodes& gc = *test.galera;
|
||||
|
||||
for (int i = 0; i < gc.N; ++i)
|
||||
{
|
||||
gc.restore_server_settings(i);
|
||||
}
|
||||
|
||||
int rc = gc.start_replication();
|
||||
test.expect(rc == 0, "Could not start Galera cluster.");
|
||||
}
|
||||
|
||||
// STOP SLAVE; START SLAVE cycle.
|
||||
void restart_slave(TestConnections& test, MYSQL* pSlave)
|
||||
{
|
||||
Row row;
|
||||
|
||||
auto replication_failed = [] (const std::string& column)
|
||||
{
|
||||
return column.find("from master when reading data from binary log: "
|
||||
"'Requested file name") != string::npos;
|
||||
};
|
||||
|
||||
test.try_query(pSlave, "STOP SLAVE");
|
||||
|
||||
row = get_row(pSlave, "SHOW SLAVE STATUS");
|
||||
auto it1 = std::find_if(row.begin(), row.end(), replication_failed);
|
||||
test.expect(it1 == row.end(), "Replication failed.");
|
||||
|
||||
test.try_query(pSlave, "START SLAVE");
|
||||
|
||||
sleep(REPLICATION_SLEEP);
|
||||
|
||||
// The START SLAVE above fails if BLR does not handle GTIDs correctly.
|
||||
row = get_row(pSlave, "SHOW SLAVE STATUS");
|
||||
auto it2 = std::find_if(row.begin(), row.end(), replication_failed);
|
||||
test.expect(it2 == row.end(), "START SLAVE failed.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
mxb::Log log(MXB_LOG_TARGET_STDOUT);
|
||||
|
||||
TestConnections::skip_maxscale_start(false);
|
||||
TestConnections test(argc, argv);
|
||||
|
||||
test.maxscales->ssh_node(0, "rm -f /var/lib/maxscale/master.ini", true);
|
||||
test.maxscales->ssh_node(0, "rm -f /var/lib/maxscale/gtid_maps.db", true);
|
||||
test.maxscales->ssh_node(0, "rm -rf /var/lib/maxscale/0", true);
|
||||
|
||||
test.start_maxscale(0);
|
||||
|
||||
setup_galera(test);
|
||||
test.galera->start_replication(); // Causes restart.
|
||||
|
||||
Mariadb_nodes& gc = *test.galera;
|
||||
gc.connect();
|
||||
|
||||
reset_galera(test);
|
||||
|
||||
string gtid = get_gtid_current_pos(test, gc.nodes[0]);
|
||||
|
||||
cout << "GTID: " << gtid << endl;
|
||||
|
||||
const char* zValue;
|
||||
|
||||
// Env-vars for debugging.
|
||||
zValue = getenv("MXS2047_BLR_HOST");
|
||||
const char* zMaxscale_host = (zValue ? zValue : test.maxscales->IP[0]);
|
||||
cout << "MaxScale host: " << zMaxscale_host << endl;
|
||||
|
||||
zValue = getenv("MXS2047_BLR_PORT");
|
||||
int maxscale_port = (zValue ? atoi(zValue) : test.maxscales->binlog_port[0]);
|
||||
cout << "MaxScale port: " << maxscale_port << endl;
|
||||
|
||||
if (setup_blr(test, gtid, zMaxscale_host, maxscale_port))
|
||||
{
|
||||
int slave_index = test.repl->N - 1; // We use the last slave.
|
||||
|
||||
Mariadb_nodes& ms = *test.repl;
|
||||
ms.connect(slave_index);
|
||||
|
||||
MYSQL* pSlave = ms.nodes[slave_index];
|
||||
mxb_assert(pSlave);
|
||||
|
||||
if (setup_slave(test, gtid, pSlave, zMaxscale_host, maxscale_port))
|
||||
{
|
||||
if (setup_schema(test, gc.nodes[0]))
|
||||
{
|
||||
sleep(REPLICATION_SLEEP);
|
||||
|
||||
if (insert_select(test, pSlave))
|
||||
{
|
||||
restart_slave(test, pSlave);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
restore_galera(test);
|
||||
|
||||
return test.global_result;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user