Merge branch '2.1' into 2.2

This commit is contained in:
Markus Mäkelä 2017-09-25 12:32:27 +03:00
commit 551bfb6f26
16 changed files with 194 additions and 13 deletions

View File

@ -21,6 +21,7 @@
* MaxScale now supports IPv6
For more details, please refer to:
* [MariaDB MaxScale 2.1.9 Release Notes](Release-Notes/MaxScale-2.1.9-Release-Notes.md)
* [MariaDB MaxScale 2.1.8 Release Notes](Release-Notes/MaxScale-2.1.8-Release-Notes.md)
* [MariaDB MaxScale 2.1.7 Release Notes](Release-Notes/MaxScale-2.1.7-Release-Notes.md)
* [MariaDB MaxScale 2.1.6 Release Notes](Release-Notes/MaxScale-2.1.6-Release-Notes.md)

View File

@ -0,0 +1,45 @@
# MariaDB MaxScale 2.1.9 Release Notes
Release 2.1.9 is a GA release.
This document describes the changes in release 2.1.9, when compared to release
[2.1.8](MaxScale-2.1.8-Release-Notes.md).
If you are upgrading from release 2.0, please also read the following release
notes:
* [2.1.8](./MaxScale-2.1.8-Release-Notes.md)
* [2.1.7](./MaxScale-2.1.7-Release-Notes.md)
* [2.1.6](./MaxScale-2.1.6-Release-Notes.md)
* [2.1.5](./MaxScale-2.1.5-Release-Notes.md)
* [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).
## Bug fixes
[Here is a list of bugs fixed in MaxScale 2.1.9.](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.9)
* [MXS-1435](https://jira.mariadb.org/browse/MXS-1435) Persistent connections can hang on COM_QUIT
* [MXS-1377](https://jira.mariadb.org/browse/MXS-1377) maxscale doesn't cleanup pid file on startup error
* [MXS-1295](https://jira.mariadb.org/browse/MXS-1295) MaxScale's readwritesplit router does not take into account the fact that stored procedure call may change the value of a user variable
## 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

@ -237,6 +237,15 @@ multi-statement queries.
router_options=strict_multi_stmt=false
```
### `strict_sp_calls`
Similar to `strict_multi_stmt`, this option allows all queries after a CALL
operation on a stored procedure to be routed to the master. This option is
disabled by default and was added in MaxScale 2.1.9.
All warnings and restrictions that apply to `strict_multi_stmt` also apply to
`strict_sp_calls`.
### `master_failure_mode`
This option controls how the failure of a master server is handled. By default,

View File

@ -7,6 +7,7 @@ For more information about MariaDB MaxScale 2.1, please refer to the
[ChangeLog](../Changelog.md).
For a complete list of changes in MaxScale 2.1, refer to the
[MaxScale 2.1.9 Release Notes](../Release-Notes/MaxScale-2.1.9-Release-Notes.md).
[MaxScale 2.1.8 Release Notes](../Release-Notes/MaxScale-2.1.8-Release-Notes.md).
[MaxScale 2.1.7 Release Notes](../Release-Notes/MaxScale-2.1.7-Release-Notes.md).
[MaxScale 2.1.6 Release Notes](../Release-Notes/MaxScale-2.1.6-Release-Notes.md).

View File

@ -7,5 +7,8 @@ then
exit 1
fi
# Script location
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
version=$1
curl -s "https://jira.mariadb.org/sr/jira.issueviews:searchrequest-csv-current-fields/temp/SearchRequest.csv?jqlQuery=project+%3D+MXS+AND+issuetype+%3D+Bug+AND+status+%3D+Closed+AND+fixVersion+%3D+$version" | process.pl
curl -s "https://jira.mariadb.org/sr/jira.issueviews:searchrequest-csv-current-fields/temp/SearchRequest.csv?jqlQuery=project+%3D+MXS+AND+issuetype+%3D+Bug+AND+status+%3D+Closed+AND+fixVersion+%3D+$version" | $DIR/process.pl

View File

@ -7,5 +7,8 @@ then
exit 1
fi
# Script location
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
version=$1
curl -s "https://jira.mariadb.org/sr/jira.issueviews:searchrequest-csv-current-fields/temp/SearchRequest.csv?jqlQuery=project+%3D+MXS+AND+issuetype+%21%3D+Bug+AND+status+%3D+Closed+AND+fixVersion+%3D+$version"|process.pl
curl -s "https://jira.mariadb.org/sr/jira.issueviews:searchrequest-csv-current-fields/temp/SearchRequest.csv?jqlQuery=project+%3D+MXS+AND+issuetype+%21%3D+Bug+AND+status+%3D+Closed+AND+fixVersion+%3D+$version" | $DIR/process.pl

View File

@ -1,4 +1,4 @@
#!/bin/perl
#!/usr/bin/env perl
# Discard the CSV headers
<>;
@ -16,5 +16,5 @@ while (<>)
my $issue = @parts[1];
my $desc = @parts[0];
print "* ($issue)[https://jira.mariadb.org/browse/$issue] $desc\n";
print "* [$issue](https://jira.mariadb.org/browse/$issue) $desc\n";
}

View File

@ -484,6 +484,12 @@ add_test_executable(mxs1319.cpp mxs1319 replication LABELS MySQLAuth REPL_BACKEN
# https://jira.mariadb.org/browse/MXS-1418
add_test_executable(mxs1418.cpp mxs1418 replication LABELS maxscale REPL_BACKEND)
# MXS-1295: MaxScale's readwritesplit router does not take into account the fact
# that stored procedure call may change the value of a user variable
#
# https://jira.mariadb.org/browse/MXS-1295
add_test_executable(mxs1295_sp_call.cpp mxs1295_sp_call mxs1295 LABELS maxscale REPL_BACKEND)
# 'namedserverfilter' test
add_test_executable(namedserverfilter.cpp namedserverfilter namedserverfilter LABELS namedserverfilter LIGHT REPL_BACKEND)

View File

@ -0,0 +1,48 @@
[maxscale]
threads=###threads###
[MySQL Monitor]
type=monitor
module=mysqlmon
###repl51###
servers=server1,server2
user=maxskysql
passwd=skysql
monitor_interval=1000
[RW Split Router]
type=service
router=readwritesplit
servers=server1,server2
user=maxskysql
passwd=skysql
strict_multi_stmt=false
strict_sp_calls=true
[RW Split Listener]
type=listener
service=RW Split 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,44 @@
/**
* Test for MXS-1295: https://jira.mariadb.org/browse/MXS-1295
*/
#include "testconnections.h"
const char sp_sql[] =
"DROP PROCEDURE IF EXISTS multi;"
"CREATE PROCEDURE multi()"
"BEGIN"
" SELECT @@server_id;"
"END";
int get_server_id(MYSQL* conn)
{
char value[200] = "";
find_field(conn, "SELECT @@server_id", "@@server_id", value);
return atoi(value);
}
int main(int argc, char *argv[])
{
TestConnections test(argc, argv);
test.connect_maxscale();
test.repl->connect();
test.tprintf("Create the stored procedure and check that it works");
test.try_query(test.repl->nodes[0], sp_sql);
test.try_query(test.repl->nodes[0], "CALL multi()");
test.tprintf("Check that queries after a CALL command get routed to the master");
int master = get_server_id(test.repl->nodes[0]);
int slave = get_server_id(test.repl->nodes[1]);
int result = get_server_id(test.conn_rwsplit);
test.add_result(result != slave, "The query should be routed to a slave(%d): %d", slave, result);
test.try_query(test.conn_rwsplit, "USE test");
test.try_query(test.conn_rwsplit, "CALL multi()");
result = get_server_id(test.conn_rwsplit);
test.add_result(result != master, "The query should be routed to the master(%d): %d", master, result);
return test.global_result;
}

View File

@ -1091,12 +1091,11 @@ static int gw_MySQLWrite_backend(DCB *dcb, GWBUF *queue)
if (MYSQL_IS_COM_QUIT((uint8_t*)GWBUF_DATA(queue)))
{
/** The COM_CHANGE_USER was already sent but the session is already
* closing. We ignore the COM_QUIT in the hopes that the response
* to the COM_CHANGE_USER comes before the DCB is closed. If the
* DCB is closed before the response arrives, the connection will
* not qualify the persistent connection pool. */
MXS_INFO("COM_QUIT received while COM_CHANGE_USER is in progress, ignoring");
* closing. */
MXS_INFO("COM_QUIT received while COM_CHANGE_USER is in progress, closing pooled connection");
gwbuf_free(queue);
poll_fake_hangup_event(dcb);
rc = 0;
}
else
{
@ -1108,8 +1107,9 @@ static int gw_MySQLWrite_backend(DCB *dcb, GWBUF *queue)
*/
MXS_INFO("COM_CHANGE_USER in progress, appending query to queue");
backend_protocol->stored_query = gwbuf_append(backend_protocol->stored_query, queue);
rc = 1;
}
return 1;
return rc;
}
/**

View File

@ -195,6 +195,10 @@ static bool rwsplit_process_router_options(Config& config,
{
config.strict_multi_stmt = config_truth_value(value);
}
else if (strcmp(options[i], "strict_sp_calls") == 0)
{
config.strict_sp_calls = config_truth_value(value);
}
else if (strcmp(options[i], "retry_failed_reads") == 0)
{
config.retry_failed_reads = config_truth_value(value);
@ -966,6 +970,8 @@ static void diagnostics(MXS_ROUTER *instance, DCB *dcb)
router->config().retry_failed_reads ? "true" : "false");
dcb_printf(dcb, "\tstrict_multi_stmt: %s\n",
router->config().strict_multi_stmt ? "true" : "false");
dcb_printf(dcb, "\tstrict_sp_calls: %s\n",
router->config().strict_sp_calls ? "true" : "false");
dcb_printf(dcb, "\tdisable_sescmd_history: %s\n",
router->config().disable_sescmd_history ? "true" : "false");
dcb_printf(dcb, "\tmax_sescmd_history: %lu\n",
@ -1036,6 +1042,8 @@ static json_t* diagnostics_json(const MXS_ROUTER *instance)
json_boolean(router->config().retry_failed_reads));
json_object_set_new(rval, "strict_multi_stmt",
json_boolean(router->config().strict_multi_stmt));
json_object_set_new(rval, "strict_sp_calls",
json_boolean(router->config().strict_sp_calls));
json_object_set_new(rval, "disable_sescmd_history",
json_boolean(router->config().disable_sescmd_history));
json_object_set_new(rval, "max_sescmd_history",
@ -1398,6 +1406,7 @@ MXS_MODULE *MXS_CREATE_MODULE()
{"disable_sescmd_history", MXS_MODULE_PARAM_BOOL, "true"},
{"max_sescmd_history", MXS_MODULE_PARAM_COUNT, "0"},
{"strict_multi_stmt", MXS_MODULE_PARAM_BOOL, "true"},
{"strict_sp_calls", MXS_MODULE_PARAM_BOOL, "false"},
{"master_accept_reads", MXS_MODULE_PARAM_BOOL, "false"},
{"connection_keepalive", MXS_MODULE_PARAM_COUNT, "0"},
{MXS_END_MODULE_PARAMS}

View File

@ -161,6 +161,7 @@ struct Config
disable_sescmd_history(config_get_bool(params, "disable_sescmd_history")),
master_accept_reads(config_get_bool(params, "master_accept_reads")),
strict_multi_stmt(config_get_bool(params, "strict_multi_stmt")),
strict_sp_calls(config_get_bool(params, "strict_sp_calls")),
retry_failed_reads(config_get_bool(params, "retry_failed_reads")),
connection_keepalive(config_get_integer(params, "connection_keepalive")),
max_slave_replication_lag(config_get_integer(params, "max_slave_replication_lag")),
@ -178,6 +179,7 @@ struct Config
bool master_accept_reads; /**< Use master for reads */
bool strict_multi_stmt; /**< Force non-multistatement queries to be routed to
* the master after a multistatement query. */
bool strict_sp_calls; /**< Lock session to master after an SP call */
bool retry_failed_reads; /**< Retry failed reads on other servers */
int connection_keepalive; /**< Send pings to servers that have been idle
* for too long */

View File

@ -118,6 +118,7 @@ bool is_read_tmp_table(RWSplitSession *router_cli_ses,
void check_create_tmp_table(RWSplitSession *router_cli_ses,
GWBUF *querybuf, uint32_t type);
bool check_for_multi_stmt(GWBUF *buf, void *protocol, uint8_t packet_type);
bool check_for_sp_call(GWBUF *buf, uint8_t packet_type);
void close_all_connections(SRWBackendList& backends);

View File

@ -183,7 +183,7 @@ bool route_single_stmt(RWSplit *inst, RWSplitSession *rses, GWBUF *querybuf, con
uint32_t qtype = info.type;
route_target_t route_target = info.target;
bool not_locked_to_master = !rses->large_query &&
(!rses->target_node || rses->target_node != rses->current_master);
(!rses->target_node || rses->target_node != rses->current_master);
if (not_locked_to_master && is_ps_command(command))
{
@ -236,6 +236,7 @@ bool route_single_stmt(RWSplit *inst, RWSplitSession *rses, GWBUF *querybuf, con
succp = handle_master_is_target(inst, rses, &target);
if (!rses->rses_config.strict_multi_stmt &&
!rses->rses_config.strict_sp_calls &&
rses->target_node == rses->current_master)
{
/** Reset the forced node as we're in relaxed multi-statement mode */
@ -774,12 +775,15 @@ handle_multi_temp_and_load(RWSplitSession *rses, GWBUF *querybuf,
* situation, assigning QUERY_TYPE_WRITE for the query will trigger
* the error processing. */
if ((rses->target_node == NULL || rses->target_node != rses->current_master) &&
check_for_multi_stmt(querybuf, rses->client_dcb->protocol, packet_type))
(check_for_multi_stmt(querybuf, rses->client_dcb->protocol, packet_type) ||
check_for_sp_call(querybuf, packet_type)))
{
if (rses->current_master)
{
rses->target_node = rses->current_master;
MXS_INFO("Multi-statement query, routing all future queries to master.");
MXS_INFO("Multi-statement query or stored procedure call, routing "
"all future queries to master.");
}
else
{

View File

@ -224,3 +224,8 @@ bool check_for_multi_stmt(GWBUF *buf, void *protocol, uint8_t packet_type)
return rval;
}
bool check_for_sp_call(GWBUF *buf, uint8_t packet_type)
{
return packet_type == MXS_COM_QUERY && qc_get_operation(buf) == QUERY_OP_CALL;
}