Merge branch '2.1' into develop

This commit is contained in:
Markus Mäkelä
2017-07-06 11:25:36 +03:00
11 changed files with 210 additions and 2 deletions

View File

@ -4,7 +4,7 @@
## About MariaDB MaxScale ## About MariaDB MaxScale
- [About MariaDB MaxScale](About/About-MaxScale.md) - [About MariaDB MaxScale](About/About-MaxScale.md)
- [Release Notes](Release-Notes/MaxScale-2.1.3-Release-Notes.md) - [Release Notes](Release-Notes/MaxScale-2.1.5-Release-Notes.md)
- [Changelog](Changelog.md) - [Changelog](Changelog.md)
- [Limitations](About/Limitations.md) - [Limitations](About/Limitations.md)

View File

@ -0,0 +1,66 @@
# MariaDB MaxScale 2.1.5 Release Notes
Release 2.1.5 is a GA release.
This document describes the changes in release 2.1.5, when compared to
release [2.1.4](MaxScale-2.1.4-Release-Notes.md).
If you are upgrading from release 2.0, please also read the following
release notes:
[2.1.4](./MaxScale-2.1.4-Release-Notes.md)
[2.1.3](./MaxScale-2.1.3-Release-Notes.md)
[2.1.2](./MaxScale-2.1.2-Release-Notes.md)
[2.1.1](./MaxScale-2.1.1-Release-Notes.md)
[2.1.0](./MaxScale-2.1.0-Release-Notes.md)
For any problems you encounter, please consider submitting a bug
report at [Jira](https://jira.mariadb.org).
## Changed Features
### Schemarouter
Starting with MaxScale 2.1.5, the _schemarouter_ will prioritize the current
database over an explicit database if tables in the the current database are
used in a query.
## New Features
### Schemarouter
A new parameter for the _schemarouter_ was added that allows deterministic
resolution of database mapping conflicts (i.e. the database exists on more than
one backend server).
The new `preferred_server` parameter takes a server name as its value. If a
database mapping conflict occurs, the server given as the parameter will have
preference. In practice, this means that databases on a central server can be
replicated to the shards for doing JOINs but writes to the replicate database
will still go to the central database.
## Bug fixes
[Here is a list of bugs fixed since the release of MaxScale 2.1.4.]
(https://jira.mariadb.org/issues/?jql=project%20%3D%20MXS%20AND%20issuetype%20%3D%20Bug%20AND%20status%20%3D%20Closed%20AND%20fixVersion%20%3D%202.1.5)
* [MXS-1310](https://jira.mariadb.org/browse/MXS-1310) schemarouter ignores local copy of duplicate schemas on JOIN
## Known Issues and Limitations
There are some limitations and known issues within this version of MaxScale.
For more information, please refer to the [Limitations](../About/Limitations.md) document.
## Packaging
RPM and Debian packages are provided for the Linux distributions supported
by MariaDB Enterprise.
Packages can be downloaded [here](https://mariadb.com/resources/downloads).
## Source Code
The source code of MaxScale is tagged at GitHub with a tag, which is identical
with the version of MaxScale. For instance, the tag of version X.Y.Z of MaxScale
is maxscale-X.Y.Z.
The source code is available [here](https://github.com/mariadb-corporation/MaxScale).

View File

@ -51,6 +51,17 @@ List of databases to ignore when checking for duplicate databases.
Regular expression that is matched against database names when checking for duplicate databases. Regular expression that is matched against database names when checking for duplicate databases.
### `preferred_server`
The name of a server in MaxScale which will be used as the preferred server when
a database is found on more than one server. If a database exists on two
servers, of which neither is the server referred by this parameter, the server
that replies first will be assigned as the location of the database.
This parameter allows deterministic conflict resolution when a sharded cluster
has a central database server and one or more sharded databases spread across
multiple servers which replicate from the central database server.
**Note:** As of version 2.1 of MaxScale, all of the router options can also be **Note:** As of version 2.1 of MaxScale, all of the router options can also be
defined as parameters. The values defined in _router_options_ will have priority defined as parameters. The values defined in _router_options_ will have priority
over the parameters. over the parameters.

View File

@ -299,6 +299,9 @@ add_test_executable(longblob.cpp longblob longblob LABELS readwritesplit readcon
# Test with extremely big blob inserting/selecting with > 16 mb data blocks # Test with extremely big blob inserting/selecting with > 16 mb data blocks
add_test_executable(mxs1110_16mb.cpp mxs1110_16mb longblob_filters LABELS readwritesplit readconnroute HEAVY REPL_BACKEND) add_test_executable(mxs1110_16mb.cpp mxs1110_16mb longblob_filters LABELS readwritesplit readconnroute HEAVY REPL_BACKEND)
# Schemarouter implicit database detection
add_test_executable(mxs1310_implicit_db.cpp mxs1310_implicit_db mxs1310_implicit_db LABELS schemarouter REPL_BACKEND)
# INSERT extremelly big number of rows # INSERT extremelly big number of rows
add_test_executable(lots_of_rows.cpp lots_of_rows galera LABELS readwritesplit HEAVY GALERA_BACKEND) add_test_executable(lots_of_rows.cpp lots_of_rows galera LABELS readwritesplit HEAVY GALERA_BACKEND)

View File

@ -0,0 +1,48 @@
[maxscale]
threads=###threads###
log_info=1
[MySQL Monitor]
type=monitor
module=mysqlmon
###repl51###
servers=server1,server2
user=maxskysql
passwd=skysql
[Sharding router]
type=service
router=schemarouter
servers=server1,server2
user=maxskysql
passwd=skysql
auth_all_servers=1
ignore_databases_regex=.*
[Sharding Listener]
type=listener
service=Sharding router
protocol=MySQLClient
port=4006
[CLI]
type=service
router=cli
[CLI Listener]
type=listener
service=CLI
protocol=maxscaled
socket=default
[server1]
type=server
address=###node_server_IP_1###
port=###node_server_port_1###
protocol=MySQLBackend
[server2]
type=server
address=###node_server_IP_2###
port=###node_server_port_2###
protocol=MySQLBackend

View File

@ -0,0 +1,54 @@
/**
* Test for MXS-1310.
* - Only explicit databases used -> shard containing the explicit database
* - Only implicit databases used -> shard containing current database
* - Mix of explicit and implicit databases -> shard containing current database
*/
#include "testconnections.h"
int main(int argc, char *argv[])
{
TestConnections test(argc, argv);
// Get the @@server_id value from both shards
char server_id[2][1024];
test.repl->connect();
sprintf(server_id[0], "%d", test.repl->get_server_id(0));
sprintf(server_id[1], "%d", test.repl->get_server_id(1));
execute_query(test.repl->nodes[0],
"CREATE DATABASE db1;"
"CREATE TABLE db1.t1(id int);"
"INSERT INTO db1.t1 VALUES (@@server_id)");
execute_query(test.repl->nodes[1],
"CREATE DATABASE db2;"
"CREATE TABLE db2.t2(id int);"
"INSERT INTO db2.t2 VALUES (@@server_id)");
test.repl->sync_slaves();
test.tprintf("Run test with sharded database as active database");
test.connect_rwsplit();
test.try_query(test.conn_rwsplit, "USE db2");
execute_query_check_one(test.conn_rwsplit, "SELECT @@server_id, id FROM t2", server_id[1]);
execute_query_check_one(test.conn_rwsplit, "SELECT @@server_id, id FROM db1.t1", server_id[0]);
execute_query_check_one(test.conn_rwsplit, "SELECT @@server_id, a.id FROM t2 as a JOIN db1.t1 as b",
server_id[1]);
test.close_rwsplit();
test.tprintf("Run test with a common database as active database");
test.connect_rwsplit();
test.try_query(test.conn_rwsplit, "USE db1");
execute_query_check_one(test.conn_rwsplit, "SELECT @@server_id, id FROM t1", server_id[0]);
execute_query_check_one(test.conn_rwsplit, "SELECT @@server_id, id FROM db2.t2", server_id[1]);
execute_query_check_one(test.conn_rwsplit, "SELECT @@server_id, a.id FROM t1 as a JOIN db1.t1 as b",
server_id[0]);
test.close_rwsplit();
// Cleanup
execute_query(test.repl->nodes[0], "DROP DATABASE db1");
execute_query(test.repl->nodes[1], "DROP DATABASE db2");
test.repl->fix_replication();
return test.global_result;
}

View File

@ -46,13 +46,15 @@ struct Config
pcre2_code* ignore_regex; /**< Regular expression used to ignore databases */ pcre2_code* ignore_regex; /**< Regular expression used to ignore databases */
pcre2_match_data* ignore_match_data; /**< Match data for @c ignore_regex */ pcre2_match_data* ignore_match_data; /**< Match data for @c ignore_regex */
std::set<std::string> ignored_dbs; /**< Set of ignored databases */ std::set<std::string> ignored_dbs; /**< Set of ignored databases */
SERVER* preferred_server; /**< Server to prefer in conflict situations */
Config(): Config():
refresh_min_interval(0.0), refresh_min_interval(0.0),
refresh_databases(false), refresh_databases(false),
debug(false), debug(false),
ignore_regex(NULL), ignore_regex(NULL),
ignore_match_data(NULL) ignore_match_data(NULL),
preferred_server(NULL)
{ {
} }
}; };

View File

@ -75,6 +75,7 @@ SchemaRouter* SchemaRouter::create(SERVICE* pService, char** pzOptions)
config.refresh_databases = config_get_bool(conf, "refresh_databases"); config.refresh_databases = config_get_bool(conf, "refresh_databases");
config.refresh_min_interval = config_get_integer(conf, "refresh_interval"); config.refresh_min_interval = config_get_integer(conf, "refresh_interval");
config.debug = config_get_bool(conf, "debug"); config.debug = config_get_bool(conf, "debug");
config.preferred_server = config_get_server(conf, "preferred_server");
/** Add default system databases to ignore */ /** Add default system databases to ignore */
config.ignored_dbs.insert("mysql"); config.ignored_dbs.insert("mysql");
@ -401,6 +402,7 @@ MXS_MODULE* MXS_CREATE_MODULE()
{"refresh_databases", MXS_MODULE_PARAM_BOOL, "true"}, {"refresh_databases", MXS_MODULE_PARAM_BOOL, "true"},
{"refresh_interval", MXS_MODULE_PARAM_COUNT, DEFAULT_REFRESH_INTERVAL}, {"refresh_interval", MXS_MODULE_PARAM_COUNT, DEFAULT_REFRESH_INTERVAL},
{"debug", MXS_MODULE_PARAM_BOOL, "false"}, {"debug", MXS_MODULE_PARAM_BOOL, "false"},
{"preferred_server", MXS_MODULE_PARAM_SERVER},
{MXS_END_MODULE_PARAMS} {MXS_END_MODULE_PARAMS}
} }
}; };

View File

@ -1322,6 +1322,14 @@ enum showdb_response SchemaRouterSession::parse_mapping_response(SSRBackend& bre
data, target->unique_name, duplicate->unique_name, data, target->unique_name, duplicate->unique_name,
m_client->user, m_client->remote); m_client->user, m_client->remote);
} }
else if (m_config->preferred_server == target)
{
/** In conflict situations, use the preferred server */
MXS_INFO("Forcing location of '%s' from '%s' to '%s'",
data, m_shard.get_location(data)->unique_name,
target->unique_name);
m_shard.replace_location(data, target);
}
} }
MXS_FREE(data); MXS_FREE(data);
} }

View File

@ -32,6 +32,12 @@ bool Shard::add_location(std::string db, SERVER* target)
return m_map.insert(std::make_pair(db, target)).second; return m_map.insert(std::make_pair(db, target)).second;
} }
void Shard::replace_location(std::string db, SERVER* target)
{
std::transform(db.begin(), db.end(), db.begin(), ::tolower);
m_map[db] = target;
}
SERVER* Shard::get_location(std::string db) SERVER* Shard::get_location(std::string db)
{ {
SERVER* rval = NULL; SERVER* rval = NULL;

View File

@ -52,6 +52,14 @@ public:
*/ */
SERVER* get_location(std::string db); SERVER* get_location(std::string db);
/**
* @brief Change the location of a database
*
* @param db Database to relocate
* @param target Target where database is relocated to
*/
void replace_location(std::string db, SERVER* target);
/** /**
* @brief Check if shard contains stale information * @brief Check if shard contains stale information
* *