Merge branch '2.2' into develop
This commit is contained in:
commit
e2fb0093b1
@ -23,7 +23,7 @@ plugin modules that tailor the behavior of the program.
|
||||
* [Monitor Modules](#monitor-modules)
|
||||
* [Filter Modules](#filter-modules)
|
||||
* [Encrypting Passwords](#encrypting-passwords)
|
||||
* [Reloading Configuration](#reloading-configuration)
|
||||
* [Runtime Configuration Changes](#runtime-configuration-changes)
|
||||
* [Authentication](#authentication)
|
||||
* [Error Reporting](#error-reporting)
|
||||
|
||||
@ -1170,7 +1170,8 @@ log with details about who tried to connect to MariaDB MaxScale and from where.
|
||||
The connection_timeout parameter is used to disconnect sessions to MariaDB
|
||||
MaxScale that have been idle for too long. The session timeouts are disabled by
|
||||
default. To enable them, define the timeout in seconds in the service's
|
||||
configuration section.
|
||||
configuration section. A value of zero is interpreted as no timeout, the same
|
||||
as if the parameter is not defined.
|
||||
|
||||
Example:
|
||||
|
||||
@ -1720,10 +1721,52 @@ password=61DD955512C39A4A8BC4BB1E5F116705
|
||||
```
|
||||
|
||||
|
||||
## Runtime Configuration Changes
|
||||
|
||||
Read the following documents for different methods of altering the MaxScale
|
||||
configuration at runtime.
|
||||
|
||||
* MaxAdmin
|
||||
* [Runtime Configuration Changes](../Reference/MaxAdmin.md#runtime-configuration-changes)
|
||||
|
||||
* MaxCtrl
|
||||
* [`create`](../Reference/MaxCtrl.md#create)
|
||||
* [`destroy`](../Reference/MaxCtrl.md#destroy)
|
||||
* [`add`](../Reference/MaxCtrl.md#add)
|
||||
* [`remove`](../Reference/MaxCtrl.md#remove)
|
||||
* [`alter`](../Reference/MaxCtrl.md#alter)
|
||||
|
||||
* [REST API](../REST-API/API.md) documentation
|
||||
|
||||
All changes to the configuration are persisted as individual configuration files
|
||||
in `/var/lib/maxscale/maxscale.cnf.d/`. These files are applied after the main
|
||||
configuration file and all auxiliary configurations have been loaded. This means
|
||||
that once runtime configurations have been made, they need to be incorporated
|
||||
into the main configuration files.
|
||||
|
||||
### Backing Up Configuration Changes
|
||||
|
||||
The combination of configuration files can be done either manually
|
||||
(e.g. `rsync`) or with the `maxscale --export-config=FILE` command line
|
||||
option. See `maxscale --help` for more information about how to use the
|
||||
`--export-config` flag.
|
||||
|
||||
For example, to export the current runtime configuration, run the following
|
||||
command.
|
||||
|
||||
```
|
||||
maxscale --export-config=/tmp/maxscale.cnf.combined
|
||||
```
|
||||
|
||||
This will create the `/tmp/maxscale.cnf.combined` file and write the current
|
||||
configuration into the it. This allows new MaxScale instances to be easily set
|
||||
up without requiring copying of all runtime configuration files.
|
||||
|
||||
## Reloading Configuration
|
||||
|
||||
**Note:** This functionality has been deprecated. Use the MaxScale REST API or the
|
||||
MaxAdmin `alter` commands to change configuration values at runtime.
|
||||
**Note:** This functionality has been deprecated and should not be used.
|
||||
|
||||
---
|
||||
|
||||
The current MariaDB MaxScale configuration may be updated by editing the
|
||||
configuration file and then forcing MariaDB MaxScale to reread the configuration
|
||||
|
@ -1,75 +1,14 @@
|
||||
# MariaDB MaxScale Installation Guide
|
||||
|
||||
## First Steps With MariaDB MaxScale
|
||||
## Normal Installation
|
||||
|
||||
In this introduction to MariaDB MaxScale the aim is to take the reader
|
||||
from the point of installation to making the decision as to which of
|
||||
the various setups that are possible with MariaDB MaxScale should be
|
||||
the initial configuration to use. One of the problems that new users to
|
||||
MariaDB MaxScale suffer is deciding exactly what they should consider
|
||||
as a base configuration to start exploring what MariaDB MaxScale
|
||||
is capable of. MariaDB MaxScale is highly configurable,
|
||||
with new plugins expanding the capabilities of MariaDB MaxScale,
|
||||
whilst this makes it a very adaptable tool it does lead to an initial
|
||||
hurdle in configuring MariaDB MaxScale.
|
||||
Download the MaxScale package from the MariaDB Downloads page:
|
||||
|
||||
## Installation
|
||||
* [https://mariadb.com/downloads/mariadb-tx/maxscale](https://mariadb.com/downloads/mariadb-tx/maxscale)
|
||||
|
||||
MariaDB MaxScale can be installed either using the MariaDB Enterprise Repository
|
||||
or directly from a downloaded package.
|
||||
|
||||
### Using the MariaDB Enterprise Repository
|
||||
|
||||
* Go to [https://mariadb.com/my_portal/download](https://mariadb.com/my_portal/download).
|
||||
|
||||
* Sign in or create an account for you.
|
||||
|
||||
* Select your operating system and follow the instructions.
|
||||
|
||||
### From a Downloaded Package
|
||||
|
||||
The MaxScale package can be downloaded from the following locations:
|
||||
|
||||
* [https://mariadb.com/my_portal/download/maxscale](https://mariadb.com/my_portal/download/maxscale)
|
||||
|
||||
* [https://mariadb.com/downloads/maxscale](https://mariadb.com/downloads/maxscale)
|
||||
|
||||
Select your operating system and download the package.
|
||||
|
||||
Depending on your OS, the package will either be a _deb_ or an _rpm_.
|
||||
|
||||
An _rpm_ is installed as follows
|
||||
```
|
||||
$ sudo yum install path-to-maxscale-package.rpm
|
||||
```
|
||||
and a _deb_ as follows
|
||||
```
|
||||
$ sudo dpkg -i path-to-maxscale-package.deb
|
||||
$ sudo apt-get install -f
|
||||
```
|
||||
|
||||
### Starting MariaDB MaxScale
|
||||
|
||||
Before starting MariaDB MaxScale, you need to create a configuration file for it;
|
||||
please see further [down](#configuring-mariadb-maxscale).
|
||||
|
||||
Once a configuration file has been created you can start MariaDB MaxScale:
|
||||
|
||||
```
|
||||
systemctl start maxscale.service
|
||||
```
|
||||
|
||||
If your system does not support systemd you can start MariaDB MaxScale using the
|
||||
installed init.d script.
|
||||
|
||||
```
|
||||
service maxscale start
|
||||
```
|
||||
|
||||
Starting with version 2.0.3, MaxScale also supports Upstart.
|
||||
|
||||
An example configuration file is installed into the `/etc/` folder.
|
||||
This file should be changed according to your needs.
|
||||
Select your operating system and download the package. You can also use
|
||||
[the MariaDB package repository](https://mariadb.com/kb/en/library/mariadb-package-repository-setup-and-usage/)
|
||||
to install MaxScale.
|
||||
|
||||
## Install MariaDB MaxScale Using a Tarball
|
||||
|
||||
@ -87,90 +26,13 @@ To do this, refer to the separate document
|
||||
|
||||
## Configuring MariaDB MaxScale
|
||||
|
||||
The first step in configuring your MariaDB MaxScale is to determine
|
||||
what it is you want to achieve with your MariaDB MaxScale and what environment
|
||||
it will run in. The later is probably the easiest starting point for choosing
|
||||
which configuration route you wish to take.
|
||||
There are two distinct database environments which the first GA release
|
||||
of MariaDB MaxScale supports; MariaDB Master/Slave Replication clusters and Galera Cluster.
|
||||
[The MaxScale Tutorial](../Tutorials/MaxScale-Tutorial.md) covers the first
|
||||
steps in configuring your MariaDB MaxScale installation. Follow this tutorial
|
||||
to learn how to configure and start using MaxScale.
|
||||
|
||||
For more details, refer to the [Configuration Guide](Configuration-Guide.md).
|
||||
|
||||
### Master/Slave Replication Clusters
|
||||
|
||||
There are two major configuration options available to use MariaDB MaxScale
|
||||
with a MariaDB Replication cluster; connection routing with separate read and
|
||||
write connections, or read/write splitting with a single connection.
|
||||
A separate tutorial is available for each of these configurations that
|
||||
describes how to build the configuration file for MariaDB MaxScale that
|
||||
will work with your environment.
|
||||
|
||||
Using a MariaDB Master/Slave Replication cluster will provide one node server
|
||||
within the cluster that is the master server and the remainder of the servers
|
||||
will be slaves. The slaves are read replicas of the master.
|
||||
In a replication cluster like this all write operations must be performed
|
||||
on the master.
|
||||
This can provide not just added security of your data, but also read scalability.
|
||||
In an application environment with a substantial proportions of read operations,
|
||||
directing those read operations to the slave servers can increase
|
||||
the total load which the system can handle by offloading the master server
|
||||
from the burden of these read operations.
|
||||
|
||||
Making the choice between these two setups is relatively simple,
|
||||
if you have an application that understands that there are some database servers
|
||||
that it can only read from and one it must send all of the writes to,
|
||||
then the connection routing option can be used.
|
||||
Applications that are not written to separate read and write statements must use
|
||||
a service within MariaDB MaxScale that will split the incoming stream of SQL statements
|
||||
into operations that can be executed on the master and those that can be set to the slave.
|
||||
These applications should use the statement based routing provided by
|
||||
the Read/Write Splitter router.
|
||||
|
||||
### Galera Cluster
|
||||
|
||||
A Galera Cluster provides a true multi-master cluster option for MariaDB and MySQL
|
||||
database environments. In such a setup any node that is part of the cluster
|
||||
can be used to both execute read and write operations.
|
||||
MariaDB MaxScale again offers two different configurations that can be used with Galera;
|
||||
a connection balancing configuration or a statement splitting mechanism that can be used
|
||||
to isolate write operations to a single node within the cluster.
|
||||
Again there is a tutorial guide available for both of these major configurations.
|
||||
|
||||
The connection based load balancing configuration is used in an environment in which
|
||||
you have a cluster that you want to be available to an application without
|
||||
the application needing to be aware of the cluster configuration or state of
|
||||
the database nodes.
|
||||
MariaDB MaxScale will monitor the nodes within the database cluster and will
|
||||
route connections from the application to database nodes that
|
||||
are active members of the cluster.
|
||||
MariaDB MaxScale will also keep track of the number of connections to each
|
||||
database node keep equal numbers of connections to each node,
|
||||
at the time the connection is established.
|
||||
|
||||
It is also possible to use the Read/Write Splitter with Galera.
|
||||
Although it is not necessary to segregate the write operations to a single node,
|
||||
there are advantages in doing this if you have an application where the write load
|
||||
is not too great to be handled by a single node in the cluster.
|
||||
Galera Cluster uses an optimistic locking strategy that will allow transactions
|
||||
to progress independently on each node within the cluster.
|
||||
It is only when the transaction commits that the transaction is checked for conflicts
|
||||
with other transactions that are committing on the other nodes.
|
||||
At this stage the commit can fail with a deadlock detection error.
|
||||
This can be inconvenient for applications and, some older applications,
|
||||
that are not aware that the transaction can fail at this stage
|
||||
may not check for this failure.
|
||||
Using the Read/Write Splitter will allow this to be avoided since
|
||||
it will isolate the write to one node and no deadlock detection will occur.
|
||||
MariaDB MaxScale provides a monitoring module that will maintain pseudo states
|
||||
of master and slave for the Galera cluster that allows for this type of configuration.
|
||||
|
||||
### Other MariaDB MaxScale Configuration
|
||||
|
||||
As well as the four major configuration choices outlined above there are also other
|
||||
configurations sub-options that may be mixed with those to provide a variety of different
|
||||
configuration and functionality. The MariaDB MaxScale filter concept allows the basic configurations
|
||||
to be built upon in a large variety of ways. A separate filter tutorial is available
|
||||
that discusses the concept and gives some examples of ways to use filters.
|
||||
For a detailed list of all configuration parameters, refer to the
|
||||
[Configuration Guide](Configuration-Guide.md) and the module specific documents
|
||||
listed in the [Documentation Contents](../Documentation-Contents.md#routers).
|
||||
|
||||
## Encrypting Passwords
|
||||
|
||||
@ -178,30 +40,13 @@ Read the [Encrypting Passwords](Configuration-Guide.md#encrypting-passwords)
|
||||
section of the configuration guide to set up password encryption for the
|
||||
configuration file.
|
||||
|
||||
## Running MariaDB MaxScale
|
||||
|
||||
MariaDB MaxScale consists of a core executable and a number of modules that implement
|
||||
the different protocols and routing algorithms. These modules are built as
|
||||
shared objects that are loaded on demand. In order for MariaDB MaxScale to find these
|
||||
modules it will search using a configurable search path. The priority of these paths are:
|
||||
|
||||
1. Look in the directory defined with --libdir=PATH during startup
|
||||
2. Look in the directory defined with libdir=PATH in the configuration file under the [maxscale] section
|
||||
3. Look in default directory in /usr/lib64/maxscale
|
||||
|
||||
Configuration is read by default from the file /etc/maxscale.cnf. An example file is
|
||||
included in in the installation and can be found in the /usr/share/maxscale folder within
|
||||
the MariaDB MaxScale installation. The -f flag can be used on the command line to set
|
||||
the name and the location of the configuration file. The -C flag can be used to set
|
||||
the directory where the configuration file is searched for. Without the -f or -C flags,
|
||||
the file is read from the /etc directory.
|
||||
|
||||
## Administration Of MariaDB MaxScale
|
||||
|
||||
There are various administration tasks that may be done with MariaDB MaxScale,
|
||||
a client command, maxadmin, is available that will interact with a running
|
||||
There are various administration tasks that may be done with MariaDB MaxScale.
|
||||
Two command line tools are available, `maxctrl` and `maxadmin`, that will interact with a running
|
||||
MariaDB MaxScale and allow the status of MariaDB MaxScale to be monitored and
|
||||
give some control of the MariaDB MaxScale functionality.
|
||||
There is [a separate reference guide](../Reference/MaxAdmin.md) for the maxadmin utility
|
||||
and also [a short administration tutorial](../Tutorials/Administration-Tutorial.md)
|
||||
that covers the common administration tasks that need to be done with MariaDB MaxScale.
|
||||
There are a separate reference guides for the [maxctrl](../Reference/MaxCtrl.md) and [maxadmin](../Reference/MaxAdmin.md) utilities.
|
||||
|
||||
[The administration tutorial](../Tutorials/Administration-Tutorial.md)
|
||||
covers the common administration tasks that need to be done with MariaDB MaxScale.
|
||||
|
@ -5,41 +5,37 @@ to a few of the common administration tasks. This is intended to be an
|
||||
introduction for administrators who are new to MariaDB MaxScale and not a
|
||||
reference to all the tasks that may be performed.
|
||||
|
||||
- [Starting MariaDB MaxScale](#starting)
|
||||
- [Stopping MariaDB MaxScale](#stopping)
|
||||
- [Checking The Status Of The MariaDB MaxScale Services](#checking)
|
||||
- [Persistent Connections](#persistent)
|
||||
- [What Clients Are Connected To MariaDB MaxScale](#clients)
|
||||
- [Rotating the Log File](#rotating)
|
||||
- [Taking A Database Server Out Of Use](#outofuse)
|
||||
## Starting and Stopping MariaDB MaxScale
|
||||
|
||||
<a name="starting"></a>
|
||||
## Starting MariaDB MaxScale
|
||||
### Systemd
|
||||
|
||||
There are several ways to start MariaDB MaxScale, the most convenient mechanism
|
||||
is probably using the Linux service interface. When a MariaDB MaxScale package
|
||||
is installed, the package manager will also install a script in /etc/init.d
|
||||
which may be used to start and stop MariaDB MaxScale either directly or via the
|
||||
service interface.
|
||||
Most modern operating systems support the Systemd interface.
|
||||
|
||||
**Starting MaxScale:**
|
||||
```
|
||||
$ service maxscale start
|
||||
systemctl start maxscale
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
**Stopping MaxScale:**
|
||||
```
|
||||
$ /etc/init.d/maxscale start
|
||||
systemctl stop maxscale
|
||||
```
|
||||
|
||||
It is also possible to start MariaDB MaxScale by executing the maxscale command
|
||||
itself. Running the executable /usr/bin/maxscale will result in MariaDB MaxScale
|
||||
running as a daemon process, unattached to the terminal in which it was started
|
||||
and using configuration files that it finds in the /etc directory.
|
||||
The MaxScale service file is located in `/lib/systemd/system/maxscale.service`.
|
||||
|
||||
Options may be passed to the MariaDB MaxScale binary that alter this default
|
||||
behavior. For a full list of all parameters, refer to the MariaDB MaxScale help
|
||||
output by executing `maxscale --help`.
|
||||
### SysV
|
||||
|
||||
Legacy platforms should use the service interface to start MaxScale.
|
||||
|
||||
**Starting MaxScale:**
|
||||
```
|
||||
service maxscale start
|
||||
```
|
||||
|
||||
**Stopping MaxScale:**
|
||||
```
|
||||
service maxscale stop
|
||||
```
|
||||
|
||||
Additional command line arguments can be passed to MariaDB MaxScale with a
|
||||
configuration file placed at `/etc/sysconfig/maxscale` on RPM installations and
|
||||
@ -51,43 +47,18 @@ quotes. The file should only contain environment variable declarations.
|
||||
MAXSCALE_OPTIONS="--logdir=/home/maxscale/logs --piddir=/tmp --syslog=no"
|
||||
```
|
||||
|
||||
<a name="stopping"></a>
|
||||
## Stopping MariaDB MaxScale
|
||||
Note that this is only supported on legacy SysV systems.
|
||||
|
||||
There are numerous ways in which MariaDB MaxScale can be stopped; using the
|
||||
service interface, killing the process or by using the maxadmin utility.
|
||||
|
||||
Stopping MariaDB MaxScale with the service interface is simply a case of using
|
||||
the service stop command or calling the init.d script with the stop argument.
|
||||
|
||||
```
|
||||
$ service maxscale stop
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
$ /etc/init.d/maxscale stop
|
||||
```
|
||||
|
||||
MariaDB MaxScale will also stop gracefully if it received a terminate signal, to
|
||||
find the process id of the MariaDB MaxScale server use the ps command or read
|
||||
the contents of the maxscale.pid file located in the /var/run/maxscale
|
||||
directory.
|
||||
|
||||
```
|
||||
$ kill `cat /var/run/maxscale/maxscale.pid`
|
||||
```
|
||||
## Stopping MariaDB MaxScale via MaxAdmin
|
||||
|
||||
In order to shutdown MariaDB MaxScale using the maxadmin command you may either
|
||||
connect with maxadmin in interactive mode or pass the "shutdown maxscale"
|
||||
command you wish to execute as an argument to maxadmin.
|
||||
|
||||
```
|
||||
$ maxadmin shutdown maxscale
|
||||
sudo maxadmin shutdown maxscale
|
||||
```
|
||||
|
||||
<a name="checking"></a>
|
||||
## Checking The Status Of The MariaDB MaxScale Services
|
||||
|
||||
It is possible to use the maxadmin command to obtain statistics about the
|
||||
@ -122,7 +93,6 @@ Network listeners count as a user of the service, therefore there will always be
|
||||
one user per network port in which the service listens. More details can be
|
||||
obtained by using the "show service" command.
|
||||
|
||||
<a name="persistent"></a>
|
||||
## Persistent Connections
|
||||
|
||||
When clients who are accessing a database system through MariaDB MaxScale make
|
||||
@ -162,7 +132,6 @@ the desired configuration. In exceptional cases this feature could be a problem.
|
||||
It is possible to have pools for as many servers as you wish, with configuration
|
||||
values in each server section.
|
||||
|
||||
<a name="clients"></a>
|
||||
## What Clients Are Connected To MariaDB MaxScale
|
||||
|
||||
To determine what client are currently connected to MariaDB MaxScale, you can
|
||||
@ -189,7 +158,6 @@ maxadmin.
|
||||
$
|
||||
```
|
||||
|
||||
<a name="rotating"></a>
|
||||
## Rotating the Log File
|
||||
|
||||
MariaDB MaxScale logs messages of different priority into a single log file.
|
||||
@ -206,20 +174,12 @@ Log file rotation is achieved by use of the "flush log" or “flush logs” comm
|
||||
in maxadmin.
|
||||
|
||||
```
|
||||
$ maxadmin flush logs
|
||||
maxadmin flush logs
|
||||
```
|
||||
|
||||
As there currently is only the maxscale log, that is the only one that will be
|
||||
rotated.
|
||||
|
||||
The maxscale log can also be flushed explicitly.
|
||||
|
||||
```
|
||||
$ maxadmin
|
||||
MaxScale> flush log maxscale
|
||||
MaxScale>
|
||||
```
|
||||
|
||||
This may be integrated into the Linux _logrotate_ mechanism by adding a
|
||||
configuration file to the /etc/logrotate.d directory. If we assume we want to
|
||||
rotate the log files once per month and wish to keep 5 log files worth of
|
||||
@ -266,14 +226,13 @@ endscript
|
||||
}
|
||||
```
|
||||
|
||||
Since MaxScale currently renames the log file, the behaviour is not fully
|
||||
In older versions MaxScale renamed the log file, behaviour which is not fully
|
||||
compliant with the assumptions of logrotate and may lead to issues, depending on
|
||||
the used logrotate configuration file. From version 2.1 onwards, MaxScale will
|
||||
not itself rename the log file, but when the log is rotated, MaxScale will
|
||||
simply close and reopen (and truncate) the same log file. That will make the
|
||||
behaviour fully compliant with logrotate.
|
||||
|
||||
<a name="outofuse"></a>
|
||||
## Taking A Database Server Out Of Use
|
||||
|
||||
MariaDB MaxScale supports the concept of maintenance mode for servers within a
|
||||
@ -286,8 +245,7 @@ may be done interactively within maxadmin or by passing the command on the
|
||||
command line.
|
||||
|
||||
```
|
||||
MaxScale> set server dbserver3 maintenance
|
||||
MaxScale>
|
||||
sudo maxadmin set server dbserver3 maintenance
|
||||
```
|
||||
|
||||
This will cause MariaDB MaxScale to stop routing any new requests to the server,
|
||||
@ -298,14 +256,8 @@ To bring the server back into service use the "clear server" command to clear
|
||||
the maintenance mode bit for that server.
|
||||
|
||||
```
|
||||
MaxScale> clear server dbserver3 maintenance
|
||||
MaxScale>
|
||||
sudo maxadmin clear server dbserver3 maintenance
|
||||
```
|
||||
|
||||
Note that maintenance mode is not persistent, if MariaDB MaxScale restarts when
|
||||
a node is in maintenance mode a new instance of MariaDB MaxScale will not honor
|
||||
this mode. If multiple MariaDB MaxScale instances are configured to use the node
|
||||
them maintenance mode must be set within each MariaDB MaxScale instance. However
|
||||
if multiple services within one MariaDB MaxScale instance are using the server
|
||||
then you only need set the maintenance mode once on the server for all services
|
||||
to take note of the mode change.
|
||||
If multiple MariaDB MaxScale instances are configured to use the node
|
||||
them maintenance mode must be set within each MariaDB MaxScale instance.
|
||||
|
@ -16,9 +16,8 @@
|
||||
|
||||
homedir=$(pwd)
|
||||
|
||||
find . -name '*.md'|while read file
|
||||
do
|
||||
cd "$(dirname "$file")"
|
||||
function check_file() {
|
||||
file=$1
|
||||
grep -o '\[.*\]([^#].*[.]md)' "$(basename "$file")"| sed -e 's/\[.*\](\(.*\))/\1/'|while read i
|
||||
do
|
||||
if [ ! -f "$i" ]
|
||||
@ -26,5 +25,15 @@ do
|
||||
echo "Link $i in $file is not correct!"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
find . -name '*.md'|while read file
|
||||
do
|
||||
cd "$(dirname "$file")"
|
||||
check_file $file
|
||||
cd "$homedir"
|
||||
done
|
||||
|
||||
cd ..
|
||||
check_file $PWD/README.md
|
||||
cd "$homedir"
|
||||
|
37
README.md
37
README.md
@ -12,18 +12,8 @@ functionality transparently to the applications. In addition it provides
|
||||
a highly scalable and flexible architecture, with plugin components to
|
||||
support different protocols and routing decisions.
|
||||
|
||||
MaxScale is implemented in C and makes extensive use of the
|
||||
asynchronous I/O capabilities of the Linux operating system. The epoll
|
||||
system is used to provide the event driven framework for the input and
|
||||
output via sockets.
|
||||
|
||||
The protocols are implemented as external shared object modules which
|
||||
can be loaded at runtime. These modules support a fixed interface,
|
||||
communicating the entries points via a structure consisting of a set of
|
||||
function pointers. This structure is called the "module object".
|
||||
|
||||
The code that routes the queries to the database servers is also loaded
|
||||
as external shared objects and are referred to as routing modules.
|
||||
For a detailed overview of what MaxScale can do, read the
|
||||
[MaxScale page on the MariaDB website](https://mariadb.com/products/technology/maxscale).
|
||||
|
||||
An Google Group exists for MaxScale that can be used to discuss ideas,
|
||||
issues and communicate with the MaxScale community.
|
||||
@ -35,18 +25,27 @@ We're also on the #maria and #maxscale channels on FreeNode.
|
||||
|
||||
Please report all feature requests, improvements and bugs in the [MariaDB Jira](https://jira.mariadb.org/projects/MXS/issues).
|
||||
|
||||
# Getting Started
|
||||
|
||||
Read the [Documentation Overview](Documentation/Documentation-Contents.md) for a
|
||||
list of all MaxScale documents.
|
||||
|
||||
- [Installing MaxScale](Documentation/Getting-Started/MariaDB-MaxScale-Installation-Guide.md)
|
||||
- [Setting up MariaDB MaxScale](Documentation/Tutorials/MaxScale-Tutorial.md)
|
||||
- [Building from Source Code](Documentation/Getting-Started/Building-MaxScale-from-Source-Code.md)
|
||||
- [Other Tutorials](Documentation/Documentation-Contents.md#tutorials)
|
||||
|
||||
# Documentation
|
||||
|
||||
For information about installing and using MaxScale, please refer to the
|
||||
documentation. The official documentation can be found on the
|
||||
The official documentation can be found on the
|
||||
[MariaDB Knowledge Base](https://mariadb.com/kb/en/mariadb-enterprise/maxscale/).
|
||||
|
||||
- [MariaDB MaxScale 2.1 Documentation](https://mariadb.com/kb/en/mariadb-enterprise/6308/)
|
||||
- [MariaDB MaxScale 2.0 Documentation](https://mariadb.com/kb/en/mariadb-enterprise/mariadb-maxscale-20-contents/)
|
||||
- [MariaDB MaxScale 1.4 Documentation](https://mariadb.com/kb/en/mariadb-enterprise/mariadb-maxscale-14/maxscale-maxscale-contents/)
|
||||
A MaxScale Troubleshooting Guide can be found on the MariaDB Knowledgebase. It
|
||||
answers common questions encountered when installing and using MaxScale.
|
||||
|
||||
The module and configuration documentation can be found in the _Documentation_
|
||||
directory of the source tree.
|
||||
The documentation can also be found in the
|
||||
[Documentation](Documentation/Documentation-Contents.md) directory of the
|
||||
source tree.
|
||||
|
||||
# Contributing Code
|
||||
|
||||
|
@ -1029,11 +1029,17 @@ add_test_executable(mxs1949_warn_user_injection.cpp mxs1949_warn_user_injection
|
||||
# MXS-1958: Users with insert-only privileges don't work
|
||||
# https://jira.mariadb.org/browse/MXS-1958
|
||||
add_test_executable(mxs1958_insert_priv.cpp mxs1958_insert_priv replication LABELS REPL_BACKEND)
|
||||
# TODO: Remove this once MXS-1958 is fixed
|
||||
set_tests_properties(mxs1958_insert_priv PROPERTIES WILL_FAIL TRUE)
|
||||
|
||||
# MXS-1849: Table family sharding router
|
||||
# https://jira.mariadb.org/browse/MXS-1849
|
||||
add_test_executable(mxs1849_table_sharding.cpp mxs1849_table_sharding mxs1849_table_sharding LABELS schemarouter BREAKS_REPL)
|
||||
|
||||
# MXS-1961: Standalone master loses master status
|
||||
# https://jira.mariadb.org/browse/MXS-1961
|
||||
add_test_executable(mxs1961_standalone_rejoin.cpp mxs1961_standalone_rejoin mxs1961_standalone_rejoin LABELS REPL_BACKEND)
|
||||
|
||||
configure_file(templates.h.in templates.h @ONLY)
|
||||
|
||||
include(CTest)
|
||||
|
@ -0,0 +1,60 @@
|
||||
[maxscale]
|
||||
threads=###threads###
|
||||
|
||||
[MySQL-Monitor]
|
||||
type=monitor
|
||||
module=mysqlmon
|
||||
servers= server1, server2, server3
|
||||
user=maxskysql
|
||||
passwd= skysql
|
||||
monitor_interval=1000
|
||||
detect_standalone_master=true
|
||||
failcount=1
|
||||
allow_cluster_recovery=true
|
||||
auto_failover=true
|
||||
auto_rejoin=true
|
||||
replication_user=repl
|
||||
replication_password=repl
|
||||
enforce_read_only_slaves=1
|
||||
verify_master_failure=false
|
||||
|
||||
[RW Split Router]
|
||||
type=service
|
||||
router= readwritesplit
|
||||
servers=server1, server2, server3
|
||||
user=maxskysql
|
||||
passwd=skysql
|
||||
|
||||
[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
|
||||
|
||||
[server3]
|
||||
type=server
|
||||
address=###node_server_IP_3###
|
||||
port=###node_server_port_3###
|
||||
protocol=MySQLBackend
|
143
maxscale-system-test/mxs1961_standalone_rejoin.cpp
Normal file
143
maxscale-system-test/mxs1961_standalone_rejoin.cpp
Normal file
@ -0,0 +1,143 @@
|
||||
/**
|
||||
* MXS-1961: Standalone master loses master status
|
||||
*/
|
||||
|
||||
#include "testconnections.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
void checkpoint(TestConnections& test)
|
||||
{
|
||||
const int v = 5;
|
||||
test.maxscales->wait_for_monitor(v);
|
||||
|
||||
for (auto&& s: {"server1", "server2", "server3"})
|
||||
{
|
||||
auto status = test.get_server_status(s);
|
||||
cout << s << " { ";
|
||||
for (auto a: status)
|
||||
{
|
||||
cout << a << ", ";
|
||||
}
|
||||
cout << "}\n";
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
Mariadb_nodes::require_gtid(true);
|
||||
TestConnections test(argc, argv);
|
||||
|
||||
auto status = [&](const char* server)
|
||||
{
|
||||
return test.get_server_status(server);
|
||||
};
|
||||
|
||||
auto comment = [&](const char* comment)
|
||||
{
|
||||
cout << comment << endl;
|
||||
test.maxscales->ssh_node_f(0, true, "echo '----- %s -----' >> /var/log/maxscale/maxscale.log", comment);
|
||||
};
|
||||
|
||||
auto slave = [&](const char* name)
|
||||
{
|
||||
static StringSet slave{"Slave", "Running"};
|
||||
test.assert(status(name) == slave, "'%s' should be a slave", name);
|
||||
};
|
||||
|
||||
auto master = [&](const char* name)
|
||||
{
|
||||
static StringSet master{"Master", "Running"};
|
||||
test.assert(status(name) == master, "'%s' should be the master", name);
|
||||
};
|
||||
|
||||
auto down = [&](const char* name)
|
||||
{
|
||||
static StringSet down{"Down"};
|
||||
test.assert(status(name) == down, "'%s' should be down", name);
|
||||
};
|
||||
|
||||
auto block = [&](int node)
|
||||
{
|
||||
test.repl->block_node(node);
|
||||
checkpoint(test);
|
||||
};
|
||||
|
||||
auto unblock = [&](int node)
|
||||
{
|
||||
test.repl->unblock_node(node);
|
||||
checkpoint(test);
|
||||
};
|
||||
|
||||
test.maxscales->wait_for_monitor(1);
|
||||
|
||||
master("server1");
|
||||
slave("server2");
|
||||
slave("server3");
|
||||
|
||||
comment("Blocking server1");
|
||||
block(0);
|
||||
comment("Blocking server2");
|
||||
block(1);
|
||||
|
||||
down("server1");
|
||||
down("server2");
|
||||
master("server3");
|
||||
|
||||
comment("Unblocking server2");
|
||||
unblock(1);
|
||||
|
||||
down("server1");
|
||||
slave("server2");
|
||||
master("server3");
|
||||
|
||||
comment("Blocking server3");
|
||||
block(2);
|
||||
comment("Unblocking server3");
|
||||
unblock(2);
|
||||
|
||||
down("server1");
|
||||
master("server2");
|
||||
slave("server3");
|
||||
|
||||
comment("Blocking server3");
|
||||
block(2);
|
||||
|
||||
down("server1");
|
||||
master("server2");
|
||||
down("server3");
|
||||
|
||||
comment("Unblocking server1");
|
||||
unblock(0);
|
||||
|
||||
slave("server1");
|
||||
master("server2");
|
||||
down("server3");
|
||||
|
||||
comment("Blocking server2");
|
||||
block(1);
|
||||
|
||||
master("server1");
|
||||
down("server2");
|
||||
down("server3");
|
||||
|
||||
comment("Unblocking server2");
|
||||
unblock(1);
|
||||
|
||||
master("server1");
|
||||
slave("server2");
|
||||
down("server3");
|
||||
|
||||
comment("Unblocking server3");
|
||||
unblock(2);
|
||||
|
||||
master("server1");
|
||||
slave("server2");
|
||||
slave("server3");
|
||||
|
||||
test.maxscales->stop();
|
||||
test.repl->fix_replication();
|
||||
|
||||
return test.global_result;
|
||||
}
|
@ -29,6 +29,7 @@
|
||||
#include <ini.h>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
#include <maxscale/adminusers.h>
|
||||
@ -221,6 +222,7 @@ static const char *config_file = NULL;
|
||||
static MXS_CONFIG gateway;
|
||||
char *version_string = NULL;
|
||||
static bool is_persisted_config = false; /**< True if a persisted configuration file is being parsed */
|
||||
static CONFIG_CONTEXT config_context;
|
||||
|
||||
const char *config_service_params[] =
|
||||
{
|
||||
@ -350,6 +352,17 @@ const char *deprecated_server_params[] =
|
||||
NULL
|
||||
};
|
||||
|
||||
void config_init()
|
||||
{
|
||||
config_context.object = (char*)"";
|
||||
config_context.next = NULL;
|
||||
}
|
||||
|
||||
void config_finish()
|
||||
{
|
||||
config_context_free(config_context.next);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the context object used for tracking duplicate sections.
|
||||
*
|
||||
@ -528,6 +541,11 @@ static bool is_empty_string(const char* str)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool is_maxscale_section(const char* section)
|
||||
{
|
||||
return strcasecmp(section, CN_GATEWAY) == 0 || strcasecmp(section, CN_MAXSCALE) == 0;
|
||||
}
|
||||
|
||||
static bool is_root_config_file = true;
|
||||
|
||||
/**
|
||||
@ -578,19 +596,7 @@ static int ini_handler(void *userdata, const char *section, const char *name, co
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(section, CN_GATEWAY) == 0 || strcasecmp(section, CN_MAXSCALE) == 0)
|
||||
{
|
||||
if (is_root_config_file || is_persisted_config)
|
||||
{
|
||||
return handle_global_item(name, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("The [maxscale] section must only be defined in the root configuration file.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else if (strlen(section) == 0)
|
||||
if (strlen(section) == 0)
|
||||
{
|
||||
MXS_ERROR("Parameter '%s=%s' declared outside a section.", name, value);
|
||||
return 0;
|
||||
@ -643,6 +649,19 @@ static int ini_handler(void *userdata, const char *section, const char *name, co
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (is_maxscale_section(section))
|
||||
{
|
||||
if (is_root_config_file || is_persisted_config)
|
||||
{
|
||||
return handle_global_item(name, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("The [maxscale] section must only be defined in the root configuration file.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -888,6 +907,59 @@ static bool contains_cnf_files(const char *path)
|
||||
return rval;
|
||||
}
|
||||
|
||||
bool export_config_file(const char* filename)
|
||||
{
|
||||
bool rval = true;
|
||||
std::vector<CONFIG_CONTEXT*> contexts;
|
||||
|
||||
// The config objects are stored in reverse order so first convert it back
|
||||
// to the correct order
|
||||
for (CONFIG_CONTEXT* ctx = config_context.next; ctx; ctx = ctx->next)
|
||||
{
|
||||
contexts.push_back(ctx);
|
||||
}
|
||||
|
||||
std::ofstream file(filename);
|
||||
|
||||
if (file)
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
file << "# Generated by MaxScale " << MAXSCALE_VERSION << '\n';
|
||||
file << "# Documentation: https://mariadb.com/kb/en/mariadb-enterprise/maxscale/ \n\n";
|
||||
|
||||
for (auto it = contexts.rbegin(); it != contexts.rend(); it++)
|
||||
{
|
||||
CONFIG_CONTEXT* ctx = *it;
|
||||
|
||||
file << '[' << ctx->object << "]\n";
|
||||
|
||||
// Parameters are also stored in reverse order
|
||||
std::vector<MXS_CONFIG_PARAMETER*> params;
|
||||
|
||||
for (MXS_CONFIG_PARAMETER* p = ctx->parameters; p; p = p->next)
|
||||
{
|
||||
params.push_back(p);
|
||||
}
|
||||
|
||||
for (auto pit = params.rbegin(); pit != params.rend(); pit++)
|
||||
{
|
||||
MXS_CONFIG_PARAMETER* p = *pit;
|
||||
file << p->name << '=' << p->value << '\n';
|
||||
}
|
||||
|
||||
file << '\n';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
MXS_ERROR("Failed to open configuration export file '%s': %d, %s",
|
||||
filename, errno, mxs_strerror(errno));
|
||||
rval = false;
|
||||
}
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Load the specified configuration file for MaxScale
|
||||
*
|
||||
@ -904,15 +976,11 @@ static bool
|
||||
config_load_and_process(const char* filename, bool (*process_config)(CONFIG_CONTEXT*))
|
||||
{
|
||||
bool rval = false;
|
||||
|
||||
DUPLICATE_CONTEXT dcontext;
|
||||
|
||||
if (duplicate_context_init(&dcontext))
|
||||
{
|
||||
CONFIG_CONTEXT ccontext = {};
|
||||
ccontext.object = (char*)"";
|
||||
|
||||
if (config_load_single_file(filename, &dcontext, &ccontext))
|
||||
if (config_load_single_file(filename, &dcontext, &config_context))
|
||||
{
|
||||
is_root_config_file = false;
|
||||
const char DIR_SUFFIX[] = ".d";
|
||||
@ -925,7 +993,7 @@ config_load_and_process(const char* filename, bool (*process_config)(CONFIG_CONT
|
||||
|
||||
if (is_directory(dir))
|
||||
{
|
||||
rval = config_load_dir(dir, &dcontext, &ccontext);
|
||||
rval = config_load_dir(dir, &dcontext, &config_context);
|
||||
}
|
||||
|
||||
/** Create the persisted configuration directory if it doesn't exist */
|
||||
@ -954,7 +1022,7 @@ config_load_and_process(const char* filename, bool (*process_config)(CONFIG_CONT
|
||||
*/
|
||||
if (duplicate_context_init(&p_dcontext))
|
||||
{
|
||||
rval = config_load_dir(persist_cnf, &p_dcontext, &ccontext);
|
||||
rval = config_load_dir(persist_cnf, &p_dcontext, &config_context);
|
||||
duplicate_context_finish(&p_dcontext);
|
||||
}
|
||||
else
|
||||
@ -966,7 +1034,7 @@ config_load_and_process(const char* filename, bool (*process_config)(CONFIG_CONT
|
||||
|
||||
if (rval)
|
||||
{
|
||||
if (!check_config_objects(ccontext.next) || !process_config(ccontext.next))
|
||||
if (!check_config_objects(config_context.next) || !process_config(config_context.next))
|
||||
{
|
||||
rval = false;
|
||||
if (contains_cnf_files(persist_cnf))
|
||||
@ -980,8 +1048,6 @@ config_load_and_process(const char* filename, bool (*process_config)(CONFIG_CONT
|
||||
}
|
||||
}
|
||||
|
||||
config_context_free(ccontext.next);
|
||||
|
||||
duplicate_context_finish(&dcontext);
|
||||
}
|
||||
return rval;
|
||||
@ -1024,6 +1090,12 @@ process_config_context(CONFIG_CONTEXT *context)
|
||||
obj = context;
|
||||
while (obj)
|
||||
{
|
||||
if (is_maxscale_section(obj->object))
|
||||
{
|
||||
obj = obj->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
char *type = config_get_value(obj->parameters, CN_TYPE);
|
||||
if (type)
|
||||
{
|
||||
@ -1058,6 +1130,12 @@ process_config_context(CONFIG_CONTEXT *context)
|
||||
obj = context;
|
||||
while (obj)
|
||||
{
|
||||
if (is_maxscale_section(obj->object))
|
||||
{
|
||||
obj = obj->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
char *type = config_get_value(obj->parameters, CN_TYPE);
|
||||
if (type)
|
||||
{
|
||||
@ -2340,6 +2418,12 @@ check_config_objects(CONFIG_CONTEXT *context)
|
||||
|
||||
while (obj)
|
||||
{
|
||||
if (is_maxscale_section(obj->object))
|
||||
{
|
||||
obj = obj->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
const char **param_set = NULL;
|
||||
const char *module = NULL;
|
||||
const char *type;
|
||||
|
@ -105,6 +105,7 @@ const char *progname = NULL;
|
||||
static struct option long_options[] =
|
||||
{
|
||||
{"config-check", no_argument, 0, 'c'},
|
||||
{"export-config", required_argument, 0, 'e'},
|
||||
{"daemon", no_argument, 0, 'n'},
|
||||
{"nodaemon", no_argument, 0, 'd'},
|
||||
{"config", required_argument, 0, 'f'},
|
||||
@ -948,6 +949,7 @@ static void usage(void)
|
||||
fprintf(stderr,
|
||||
"\nUsage : %s [OPTION]...\n\n"
|
||||
" -c, --config-check validate configuration file and exit\n"
|
||||
" -e, --export-config=FILE export configuration to a single file\n"
|
||||
" -d, --nodaemon enable running in terminal process\n"
|
||||
" -f, --config=FILE relative or absolute pathname of config file\n"
|
||||
" -l, --log=[file|shm|stdout] log to file, shared memory or stdout\n"
|
||||
@ -1334,7 +1336,9 @@ int main(int argc, char **argv)
|
||||
bool pid_file_created = false;
|
||||
Worker* worker;
|
||||
const char* specified_user = NULL;
|
||||
char export_cnf[PATH_MAX + 1] = "";
|
||||
|
||||
config_init();
|
||||
config_set_global_defaults();
|
||||
ss_dassert(cnf);
|
||||
|
||||
@ -1348,7 +1352,7 @@ int main(int argc, char **argv)
|
||||
file_write_header(stderr);
|
||||
|
||||
// Option string for getopt
|
||||
const char accepted_opts[] = "dncf:g:l:vVs:S:?L:D:C:B:U:A:P:G:N:E:F:M:H:p";
|
||||
const char accepted_opts[] = "dnce:f:g:l:vVs:S:?L:D:C:B:U:A:P:G:N:E:F:M:H:p";
|
||||
|
||||
/*<
|
||||
* Register functions which are called at exit.
|
||||
@ -1654,6 +1658,11 @@ int main(int argc, char **argv)
|
||||
cnf->config_check = true;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
cnf->config_check = true;
|
||||
strcpy(export_cnf, optarg);
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
cnf->passive = true;
|
||||
break;
|
||||
@ -2087,6 +2096,12 @@ int main(int argc, char **argv)
|
||||
if (cnf->config_check)
|
||||
{
|
||||
MXS_NOTICE("Configuration was successfully verified.");
|
||||
|
||||
if (*export_cnf && export_config_file(export_cnf))
|
||||
{
|
||||
MXS_NOTICE("Configuration exported to '%s'", export_cnf);
|
||||
}
|
||||
|
||||
rc = MAXSCALE_SHUTDOWN;
|
||||
goto return_main;
|
||||
}
|
||||
@ -2231,6 +2246,8 @@ return_main:
|
||||
MXS_FREE(cnf_file_path);
|
||||
}
|
||||
|
||||
config_finish();
|
||||
|
||||
return rc;
|
||||
} /*< End of main */
|
||||
|
||||
|
@ -47,6 +47,16 @@ extern const char *config_filter_params[];
|
||||
extern const char *config_server_params[];
|
||||
extern const char *config_pre_parse_global_params[];
|
||||
|
||||
/**
|
||||
* Initialize the configuration subsystem
|
||||
*/
|
||||
void config_init();
|
||||
|
||||
/**
|
||||
* Finalize the configuration subsystem
|
||||
*/
|
||||
void config_finish();
|
||||
|
||||
/**
|
||||
* Set the defaults for the global configuration options
|
||||
*/
|
||||
@ -174,4 +184,13 @@ void fix_section_name(char *section);
|
||||
*/
|
||||
bool config_global_serialize();
|
||||
|
||||
/**
|
||||
* Export the configuration to a file
|
||||
*
|
||||
* @param filename Filename where the configuration will be written
|
||||
*
|
||||
* @return True if configuration was successfully exported
|
||||
*/
|
||||
bool export_config_file(const char* filename);
|
||||
|
||||
MXS_END_DECLS
|
||||
|
Loading…
x
Reference in New Issue
Block a user