You are here

Sharding mit MariaDB MaxScale

Inhaltsverzeichnis


Übersicht

Dieses Feature sollte mehr oder weniger mit MariaDB MaxScale 6.x.y, 22.08.x, 23.02.x, 23.08.x und 24.02.x funktionieren. Wir haben es mit der neusten MaxScale Version 23.08.05 getestet, da wir mit einer älteren Version auf Problem gestossen sind (MXS-5026).

shell> maxscale --version
MaxScale 23.08.5

Als Datenbank Backend (Shards) haben wir MariaDB 10.11 verwendet.

Weniger als ca 2% aller uns bekannten MariaDB Installationen sind das, was wir technische unter Multi-Mandanten-Systeme (multi-tenant systems) verstehen (jeder Mandant (Kunde) in einer eigenen Datenbank (auch Schema genannt)).

Daher wird dieses MariaDB MaxScale Feature relativ selten genutzt und es besteht die erhöhte Gefahr auf Bugs zu stossen, auf welche vorher noch niemand gestossen ist!

Dieses Feature wird bei MariadDB MaxScale: SchemaRouter genannt und wird immer noch als Beta-Qualität deklariert (MXS-5025):

maxctrl> show module schemarouter
┌─────────────┬────────────────────────────────────────────────┐
│ Module      │ schemarouter                                   │
├─────────────┼────────────────────────────────────────────────┤
│ Type        │ Router                                         │
├─────────────┼────────────────────────────────────────────────┤
│ Version     │ V1.0.0                                         │
├─────────────┼────────────────────────────────────────────────┤
│ Maturity    │ Beta                                           │
├─────────────┼────────────────────────────────────────────────┤
│ Description │ A database sharding router for simple sharding │
├─────────────┼────────────────────────────────────────────────┤
│ ...

Die Ziel-Topologie soll wie folgt aussehen: Jeder Kunde (Mandant, Tenant) liegt in einer eigenen Datenbank (= Schema). Die Datenbanken sind über mehrere MariaDB Instanzen (Shards) verteilt. Damit die Applikation transparent auf die Datenbank zugreifen kann wird ein Pärchen MaxScale Load Balancer davor geschaltet, welches weiss, wo der Kunde liegt und den Traffic entsprechend an das Shard weiterleitet. Damit die MaxScale Load Balancer hochverfügbar ausgelegt sind, wird noch eine virtuelle IP (VIP) z.B. mittels Keepalived vorgeschaltet. Wem das noch zu einfach ist, der kann jedes einzelne Shard noch als Master/Slave- oder Galera Cluster-Konstrukt auslegen...

Vorbereitung der Shards (MariaDB Datenbank Instanzen)

Als erstes hatten wir bei diesem PoC Problem mit der test Datenbank. Durch das Löschen der test Datenbank auf allen Shards ist das Problem verschwunden. Alternativ dazu kann man mariadb-secure-installation ausführen, was man auf Produktionsystemen sowieso machen sollte, oder man nutzt die MaxScale Konfigurationsparameter: ignore_tables oder ignore_tables_regex um gleiche Tabellen in unterschiedlichen Shards zu erlauben (MXS-5027).

Siehe auch: MaxScale Router Parameters.

Testdaten erstellen

Damit wir was zum Spielen haben, haben wir uns Testdaten erstellt:

-- Auf Shard 1: 2 Kunden

SQL> CREATE DATABASE customer_0010;
SQL> CREATE TABLE customer_0010.address (id INT UNSIGNED, name VARCHAR(255));
SQL> CREATE TABLE customer_0010.sales (id INT UNSIGNED, product VARCHAR(255), sales TINYINT, amount DECIMAL(6, 2), total_amount DECIMAL(6, 2));
SQL> INSERT INTO customer_0010.address VALUES (1, 'Customer 10 GmbH');
SQL> INSERT INTO customer_0010.sales VALUES (1, 'Apples', 5, 1.2, 6), (2, 'Pears', 2, 0.9, 1.8), (3, 'Bread', 1, 2.5, 2.5);

SQL> CREATE DATABASE customer_0011;
SQL> CREATE TABLE customer_0011.address (id INT UNSIGNED, name VARCHAR(255));
SQL> CREATE TABLE customer_0011.sales (id INT UNSIGNED, product VARCHAR(255), sales TINYINT, amount DECIMAL(6, 2), total_amount DECIMAL(6, 2));
SQL> INSERT INTO customer_0011.address VALUES (1, 'Customer 11 SE');
SQL> INSERT INTO customer_0011.sales VALUES (1, 'Oranges', 2, 1.7, 3.4), (2, 'Salat', 5, 1.2, 6);

-- Auf Shard 2: 3 Kunden

SQL> CREATE DATABASE customer_0020;
SQL> CREATE TABLE customer_0020.address (id INT UNSIGNED, name VARCHAR(255));
SQL> CREATE TABLE customer_0020.sales (id INT UNSIGNED, product VARCHAR(255), sales TINYINT, amount DECIMAL(6, 2), total_amount DECIMAL(6, 2));
SQL> INSERT INTO customer_0020.address VALUES (1, 'Customer 20 AG');
SQL> INSERT INTO customer_0020.sales VALUES (1, 'Oranges', 2, 1.7, 3.4), (2, 'Salat', 5, 1.2, 6);

SQL> CREATE DATABASE customer_0021;
SQL> CREATE TABLE customer_0021.address (id INT UNSIGNED, name VARCHAR(255));
SQL> CREATE TABLE customer_0021.sales (id INT UNSIGNED, product VARCHAR(255), sales TINYINT, amount DECIMAL(6, 2), total_amount DECIMAL(6, 2));
SQL> INSERT INTO customer_0021.address VALUES (1, 'Customer 21 GmbH');
SQL> INSERT INTO customer_0021.sales VALUES (1, 'Oranges', 2, 1.7, 3.4), (2, 'Salat', 5, 1.2, 6);

SQL> CREATE DATABASE customer_0022;
SQL> CREATE TABLE customer_0022.address (id INT UNSIGNED, name VARCHAR(255));
SQL> CREATE TABLE customer_0022.sales (id INT UNSIGNED, product VARCHAR(255), sales TINYINT, amount DECIMAL(6, 2), total_amount DECIMAL(6, 2));
SQL> INSERT INTO customer_0022.address VALUES (1, 'Customer 22 Gebr.');
SQL> INSERT INTO customer_0022.sales VALUES (1, 'Oranges', 2, 1.7, 3.4), (2, 'Salat', 5, 1.2, 6);

-- Auf Shard 3: 1 Kunde

SQL> CREATE DATABASE customer_0030;
SQL> CREATE TABLE customer_0030.address (id INT UNSIGNED, name VARCHAR(255));
SQL> CREATE TABLE customer_0030.sales (id INT UNSIGNED, product VARCHAR(255), sales TINYINT, amount DECIMAL(6, 2), total_amount DECIMAL(6, 2));
SQL> INSERT INTO customer_0030.address VALUES (1, 'Customer 30 GmbH');
SQL> INSERT INTO customer_0030.sales VALUES (1, 'Pickles', 2, 2.2, 4.4), (2, 'Salat', 1, 3.1, 3.1), (3, 'Pudding', 5, 2.2, 11.0), (4, 'Asparagus', 12, .3, 3.6);

Rollen und User erstellen

Da in einem geshardeten System, im Unterschied zum Beispiel zu einem Galera Cluster, die einzelnen Datenbank-Instanzen nichts voneinander wissen und nicht miteinander kommunizieren, müssen wir die Rollen und User bzw. Accounts jeweils auf JEDEM Shard einzeln anlegen.

MariaDB MaxScale braucht jeweils für den SchemaRouter Service und den Monitor einen User (auf jedem Shard).

Der Monitor User ist, wie der Name sagt fürs Monitoring zuständig und der SchemaRouter Service User um die User Account Informationen aus den Sharding-Backends einzusammeln und die Queries an das richtige Shard weiterzuleiten.

Da in einem redundanten System typischerweise mit mindestens zwei MaxScale Routern gearbeitet wird und wir dem auseinanderlaufen der Privilegien der Accounts vorbeugen wollten arbeiten wir mit Rollen sowohl für die MaxScale User als auch die applikatorischen User.

MaxScale Monitor User

SQL> CREATE ROLE maxscale_monitor_role;

SQL> GRANT SELECT ON mysql.user TO 'maxscale_monitor_role';
SQL> GRANT REPLICATION CLIENT ON *.* TO 'maxscale_monitor_role';
SQL> GRANT SLAVE MONITOR ON *.* TO 'maxscale_monitor_role';
SQL> GRANT FILE ON *.* TO 'maxscale_monitor_role';
SQL> GRANT CONNECTION ADMIN ON *.* TO 'maxscale_monitor_role';

SQL> SHOW GRANTS FOR maxscale_monitor_role;
+-----------------------------------------------------------------------------------------------+
| Grants for maxscale_monitor_role                                                              |
+-----------------------------------------------------------------------------------------------+
| GRANT FILE, BINLOG MONITOR, CONNECTION ADMIN, SLAVE MONITOR ON *.* TO `maxscale_monitor_role` |
| GRANT SELECT ON `mysql`.`user` TO `maxscale_monitor_role`                                     |
+-----------------------------------------------------------------------------------------------+

SQL> CREATE USER maxscale_monitor@'10.139.158.210' IDENTIFIED BY 'secret';
SQL> CREATE USER maxscale_monitor@'10.139.158.211' IDENTIFIED BY 'secret';

SQL> GRANT maxscale_monitor_role TO maxscale_monitor@'10.139.158.210';
SQL> GRANT maxscale_monitor_role TO maxscale_monitor@'10.139.158.211';

SQL> SET DEFAULT ROLE maxscale_monitor_role FOR maxscale_monitor@'10.139.158.210';
SQL> SET DEFAULT ROLE maxscale_monitor_role FOR maxscale_monitor@'10.139.158.211';

SQL> SELECT user, host, is_role, default_role FROM mysql.user WHERE user LIKE 'maxscale_monitor%';
+-----------------------+----------------+---------+-----------------------+
| User                  | Host           | is_role | default_role          |
+-----------------------+----------------+---------+-----------------------+
| maxscale_monitor_role |                | Y       |                       |
| maxscale_monitor      | 10.139.158.210 | N       | maxscale_monitor_role |
| maxscale_monitor      | 10.139.158.211 | N       | maxscale_monitor_role |
+-----------------------+----------------+---------+-----------------------+

SQL> SHOW GRANTS FOR maxscale_monitor@'10.139.158.211';
+------------------------------------------------------------------------------------------------------------------------------+
| Grants for maxscale_monitor@10.139.158.211                                                                                   |
+------------------------------------------------------------------------------------------------------------------------------+
| GRANT `maxscale_monitor_role` TO `maxscale_monitor`@`10.139.158.211`                                                         |
| GRANT USAGE ON *.* TO `maxscale_monitor`@`10.139.158.211` IDENTIFIED BY PASSWORD '*14E65567ABDB5135D0CFD9A70B3032C179A49EE7' |
| SET DEFAULT ROLE `maxscale_monitor_role` FOR `maxscale_monitor`@`10.139.158.211`                                             |
+------------------------------------------------------------------------------------------------------------------------------+

MaxScale Admin User

SQL> CREATE ROLE maxscale_admin_role;

SQL> GRANT SHOW DATABASES ON *.* TO 'maxscale_admin_role';
SQL> GRANT SELECT ON mysql.user TO 'maxscale_admin_role';
SQL> GRANT SELECT ON mysql.db TO 'maxscale_admin_role';
SQL> GRANT SELECT ON mysql.tables_priv TO 'maxscale_admin_role';
SQL> GRANT SELECT ON mysql.columns_priv TO 'maxscale_admin_role';
SQL> GRANT SELECT ON mysql.proxies_priv TO 'maxscale_admin_role';
SQL> GRANT SELECT ON mysql.roles_mapping TO 'maxscale_admin_role';
SQL> GRANT SELECT ON mysql.procs_priv TO 'maxscale_admin_role';

SQL> SHOW GRANTS FOR maxscale_admin_role;
+------------------------------------------------------------------+
| Grants for maxscale_admin_role                                   |
+------------------------------------------------------------------+
| GRANT USAGE ON *.* TO `maxscale_admin_role`                      |
| GRANT SELECT ON `mysql`.`user` TO `maxscale_admin_role`          |
| GRANT SELECT ON `mysql`.`roles_mapping` TO `maxscale_admin_role` |
| GRANT SELECT ON `mysql`.`tables_priv` TO `maxscale_admin_role`   |
| GRANT SELECT ON `mysql`.`procs_priv` TO `maxscale_admin_role`    |
| GRANT SELECT ON `mysql`.`db` TO `maxscale_admin_role`            |
| GRANT SELECT ON `mysql`.`columns_priv` TO `maxscale_admin_role`  |
| GRANT SELECT ON `mysql`.`proxies_priv` TO `maxscale_admin_role`  |
+------------------------------------------------------------------+

SQL> CREATE USER maxscale_admin@'10.139.158.210' IDENTIFIED BY 'secret';
SQL> CREATE USER maxscale_admin@'10.139.158.211' IDENTIFIED BY 'secret';

SQL> GRANT maxscale_admin_role TO maxscale_admin@'10.139.158.210';
SQL> GRANT maxscale_admin_role TO maxscale_admin@'10.139.158.211';

SQL> SET DEFAULT ROLE maxscale_admin_role FOR maxscale_admin@'10.139.158.210';
SQL> SET DEFAULT ROLE maxscale_admin_role FOR maxscale_admin@'10.139.158.211';

SQL> SELECT user, host, is_role, default_role FROM mysql.user WHERE user LIKE 'maxscale_admin%';
+---------------------+----------------+---------+---------------------+
| User                | Host           | is_role | default_role        |
+---------------------+----------------+---------+---------------------+
| maxscale_admin_role |                | Y       |                     |
| maxscale_admin      | 10.139.158.210 | N       | maxscale_admin_role |
| maxscale_admin      | 10.139.158.211 | N       | maxscale_admin_role |
+---------------------+----------------+---------+---------------------+

SQL> SHOW GRANTS FOR maxscale_admin@'10.139.158.211';
+----------------------------------------------------------------------------------------------------------------------------+
| Grants for maxscale_admin@10.139.158.211                                                                                   |
+----------------------------------------------------------------------------------------------------------------------------+
| GRANT `maxscale_admin_role` TO `maxscale_admin`@`10.139.158.211`                                                           |
| GRANT USAGE ON *.* TO `maxscale_admin`@`10.139.158.211` IDENTIFIED BY PASSWORD '*14E65567ABDB5135D0CFD9A70B3032C179A49EE7' |
| SET DEFAULT ROLE `maxscale_admin_role` FOR `maxscale_admin`@`10.139.158.211`                                               |
+----------------------------------------------------------------------------------------------------------------------------+

Siehe dazu auch: SchemaRouter Configuration

Applikationsrolle und Accounts erstellen

Für die Applikation braucht es ebenfalls einen User, den wir hier wie auf jedem Shard wie folgt erstellen:

SQL> CREATE ROLE app_role;
SQL> GRANT SELECT, INSERT, UPDATE, DELETE ON `customer_%`.* TO 'app_role';
SQL> GRANT SHOW DATABASES ON *.* TO 'app_role';
SQL> GRANT CREATE, DROP, ALTER ON *.* TO 'app_role';   -- For creating new tenant databases

SQL> SHOW GRANTS FOR app_role;
+----------------------------------------------------------------------+
| Grants for app_role                                                  |
+----------------------------------------------------------------------+
| GRANT SHOW DATABASES ON *.* TO `app_role`                            |
| GRANT SELECT, INSERT, UPDATE, DELETE ON `customer_%`.* TO `app_role` |
+----------------------------------------------------------------------+

SQL> CREATE USER app@'10.139.158.%' IDENTIFIED BY 'secret';
SQL> GRANT app_role TO app@'10.139.158.%';
SQL> SET DEFAULT ROLE app_role FOR app@'10.139.158.%';

SQL> SELECT user, host, is_role, default_role FROM mysql.user WHERE user LIKE 'app%';
+----------+--------------+---------+--------------+
| User     | Host         | is_role | default_role |
+----------+--------------+---------+--------------+
| app_role |              | Y       |              |
| app      | 10.139.158.% | N       | app_role     |
+----------+--------------+---------+--------------+

SQL> SHOW GRANTS FOR app@'10.139.158.%';
+---------------------------------------------------------------------------------------------------------------+
| Grants for app@10.139.158.%                                                                                   |
+---------------------------------------------------------------------------------------------------------------+
| GRANT `app_role` TO `app`@`10.139.158.%`                                                                      |
| GRANT USAGE ON *.* TO `app`@`10.139.158.%` IDENTIFIED BY PASSWORD '*14E65567ABDB5135D0CFD9A70B3032C179A49EE7' |
| SET DEFAULT ROLE `app_role` FOR `app`@`10.139.158.%`                                                          |
+---------------------------------------------------------------------------------------------------------------+

Proxy Protokoll

Load Balancer und Proxies haben die Eigenschaft, dass sie die IP Adressen der Clients durch ihre eigenen IP Adressen austauschen. Dies führt einerseits dazu, dass man auf der Datenbank nicht mehr sieht, woher der Client ursprünglich kommt, andererseits kann man die Zugriffsberechtigungen nicht mehr auf User und IP vergeben, da immer gegen die IP der Load Balancer geprüft wird.

Diese beiden Probleme können mittels des Proxy Protokolls gelöst werden.

Hierzu müssen einerseits die Datenbank und andererseits die Load Balancer, in diesem Fall der MaxScale, das Proxy Protokoll aktiviert haben.

Auf der Datenbank-Seite aktiviert man das Proxy Protokoll wie folgt:

#
# my.cnf
#

[mariadbd]

proxy_protocol_networks = ::1, 10.139.158.0/24, localhost

und auf MaxScale-Seite mit:

#
# /etc/maxscale.cnf
#

[shard<n>]
type = server
proxy_protocol = true

Überprüfen kann man die beiden Einstellungen mit:

SQL> SHOW GLOBAL VARIABLES LIKE 'proxy%';
+-------------------------+---------------------------------+
| Variable_name           | Value                           |
+-------------------------+---------------------------------+
| proxy_protocol_networks | ::1, 10.139.158.0/24, localhost |
+-------------------------+---------------------------------+

shell> maxctrl show server shard1 | grep proxy
│                     │     "proxy_protocol": true,                  │

Quellen:


MaxScale SchemaRouter Konfiguration

Als nächstes bereiten wir die MaxScale Konfiguration fürs Sharding vor. Die von MariaDB empfohlene Datei ist /etc/maxscale.cnf. Ob es sinnvoller ist eine eigene Konfigurations-Datei unter /etc/maxscale.cnf.d/ zu erstellen oder gar den ganze MaxScale dynamisch zu konfigurieren (/var/lib/maxscale/maxscale.cnf.d/*.cnf), wird sich langfristig zeigen. Siehe auch Warnungen weiter unten. Die Konfigurationsdatei für dieses Sharding PoC sieht wie folgt aus:

#
# /etc/maxscale.cnf
#

[maxscale]
threads = auto
admin_gui = false

[shard1]
type = server
address = 10.139.158.1
port = 3363
proxy_protocol = true

[shard2]
type=server
address=10.139.158.1
port=3364
proxy_protocol = true

[shard3]
type = server
address = 10.139.158.1
port = 3365
proxy_protocol = true

[Sharding-Monitor]
type = monitor
module = galeramon
servers = shard1,shard2,shard3
user = maxscale_monitor
password = secret
monitor_interval = 1s

[Sharded-Service-Listener]
type = listener
service = Sharded-Service
protocol = MariaDBClient
port = 3306

[Sharded-Service]
type = service
router = schemarouter
servers = shard1,shard2,shard3
user = maxscale_admin
password = secret
auth_all_servers = true

Hinweis: Empfehlung des MaxScale Entwicklers: "One workaround might be to actually use galeramon to monitor the nodes instead of mariadbmon."

Starten und Stoppen des MaxScale Load Balancers

Starten und Stoppen von MaxScale erfolgt wie üblich über SystemD:

shell> systemctl restart maxscale

shell> systemctl status maxscale
● maxscale.service - MariaDB MaxScale Database Proxy
     Loaded: loaded (/lib/systemd/system/maxscale.service; enabled; vendor preset: enabled)
    Drop-In: /run/systemd/system/service.d
             └─zzz-lxc-service.conf
     Active: active (running) since Tue 2024-02-27 09:52:57 UTC; 39s ago
    Process: 187 ExecStart=/usr/bin/maxscale (code=exited, status=0/SUCCESS)
   Main PID: 188 (maxscale)
      Tasks: 10 (limit: 18663)
     Memory: 4.6M
        CPU: 150ms
     CGroup: /system.slice/maxscale.service
             └─188 /usr/bin/maxscale

systemd[1]: Starting MariaDB MaxScale Database Proxy...
maxscale[188]: Module 'galeramon' loaded from '/usr/lib/x86_64-linux-gnu/maxscale/libgaleramon.so'.
maxscale[188]: Module 'schemarouter' loaded from '/usr/lib/x86_64-linux-gnu/maxscale/libschemarouter.so'.
maxscale[188]: Using up to 2.3GiB of memory for query classifier cache
systemd[1]: Started MariaDB MaxScale Database Proxy.

Falls es Fehler oder Warnungen gegeben hat, kann man diese im MaxScale Error Log sehen:

shell> grep -v notice /var/log/maxscale/maxscale.log
2024-02-13 16:47:22   MariaDB MaxScale is shut down.
----------------------------------------------------


MariaDB MaxScale  /var/log/maxscale/maxscale.log  Tue Feb 13 16:47:22 2024
----------------------------------------------------------------------------
2024-02-27 09:52:56   warning: Discarding journal file '/var/lib/maxscale/Sharding-Monitor_journal.json'. File is for module 'mariadbmon'. Current module is 'galeramon'.
2024-02-27 09:52:56   warning: [galeramon] Invalid 'wsrep_local_index' on server 'shard1': 18446744073709551615

Applikations-Tests

Einfache Applikations-Tests

shell> mariadb --user=app --password=secret --host=10.139.158.211 --port=3306 --execute='show databases'
+--------------------+
| Database           |
+--------------------+
| customer_0010      |
| customer_0011      |
| customer_0020      |
| customer_0021      |
| customer_0022      |
| customer_0030      |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+

Neuer Befehl show shards

shell> mariadb --user=app --password=secret --host=10.139.158.211 --port=3306 customer_0030 --execute='show shards' | grep customer_00.* | sort | column -t
customer_0010.address  shard1
customer_0010.sales    shard1
customer_0010.         shard1
customer_0011.address  shard1
customer_0011.sales    shard1
customer_0011.         shard1
customer_0020.address  shard2
customer_0020.sales    shard2
customer_0020.         shard2
customer_0021.address  shard2
customer_0021.sales    shard2
customer_0021.         shard2
customer_0022.address  shard2
customer_0022.sales    shard2
customer_0022.         shard2
customer_0030.address  shard3
customer_0030.sales    shard3
customer_0030.         shard3

Neue Datenbanken werden nicht sofort angezeigt, sondern erst wenn die gecachten Daten upgedatet wurden (refresh_interval (300s / 5 min)).

Siehe hierzu auch: Custom SQL commands

Allgemeinere Test

Zur Erinnerung:

ShardPortCustomerState
#13363customer_001<n>Running
#23364customer_002<n>Running
#33365customer_003<n>Running
#43366customer_004<n>Running

shell> mariadb --user=app --password=secret --host=10.139.158.211 --port=3306 --execute='SELECT @@port'
+--------+
| @@port |
+--------+
|   3363 |
+--------+
shell> mariadb --user=app --password=secret --host=10.139.158.211 --port=3306 --database=customer_0010 --execute='SELECT @@port'
+--------+
| @@port |
+--------+
|   3363 |
+--------+
shell> mariadb --user=app --password=secret --host=10.139.158.211 --port=3306 --database=customer_0020 --execute='SELECT @@port'
+--------+
| @@port |
+--------+
|   3364 |
+--------+
shell> mariadb --user=app --password=secret --host=10.139.158.211 --port=3306 --execute='use customer_0020; SELECT @@port'
+--------+
| @@port |
+--------+
|   3364 |
+--------+
shell> mariadb --user=app --password=secret --host=10.139.158.211 --port=3306 customer_0010 --execute='SELECT @@port'
+--------+
| @@port |
+--------+
|   3363 |
+--------+
shell> mariadb --user=app --password=secret --host=10.139.158.211 --port=3306 customer_0020 --execute='SELECT @@port'
+--------+
| @@port |
+--------+
|   3364 |
+--------+
shell> mariadb --user=app --password=secret --host=10.139.158.211 --port=3306 customer_0030 --execute='SELECT @@port'
+--------+
| @@port |
+--------+
|   3365 |
+--------+

Weniger einfache (Backup-) Test

shell> mariadb-dump --user=app --password=secret --host=10.139.158.211 --port=3306 --single-transaction customer_0010 > /tmp/customer_0010.sql
shell> echo $?
0
shell> mariadb-dump --user=app --password=secret --host=10.139.158.211 --port=3306 --single-transaction customer_0020 > /tmp/customer_0020.sql
shell> echo $?
0
shell> mariadb-dump --user=app --password=secret --host=10.139.158.211 --port=3306 --single-transaction customer_0030 > /tmp/customer_0030.sql
shell> echo $?
0
shell> mariadb-dump --user=app --password=secret --host=10.139.158.211 --port=3306 --single-transaction --databases customer_0011 > /tmp/customer_0011.sql
shell> echo $?
0
shell> mariadb-dump --user=app --password=secret --host=10.139.158.211 --port=3306 --single-transaction --databases customer_0021 > /tmp/customer_0021.sql
shell> echo $?
0
shell> mariadb-dump --user=app --password=secret --host=10.139.158.211 --port=3306 --single-transaction --databases customer_0030 > /tmp/customer_0030.sql
shell> echo $?
0

shell> ll /tmp/customer_00*sql
-rw-rw-r-- 1 oli oli 2738 Mar 18 12:07 /tmp/customer_0010.sql
-rw-rw-r-- 1 oli oli 2904 Mar 18 12:08 /tmp/customer_0011.sql
-rw-rw-r-- 1 oli oli 2712 Mar 18 12:08 /tmp/customer_0020.sql
-rw-rw-r-- 1 oli oli 2906 Mar 18 12:08 /tmp/customer_0021.sql
-rw-rw-r-- 1 oli oli 2964 Mar 18 12:08 /tmp/customer_0030.sql

shell> tail -n 1 /tmp/customer_*.sql
==> /tmp/customer_0010.sql <==
-- Dump completed on 2024-02-13 14:39:21

==> /tmp/customer_0011.sql <==
-- Dump completed on 2024-02-13 14:39:35

==> /tmp/customer_0020.sql <==
-- Dump completed on 2024-02-13 14:40:15

==> /tmp/customer_0021.sql <==
-- Dump completed on 2024-02-13 14:40:42

==> /tmp/customer_0030.sql <==
-- Dump completed on 2024-02-13 14:40:52

shell> cat /tmp/customer_00*sql | grep -A1 -i insert
INSERT INTO `address` VALUES
(1,'Customer 10 GmbH');
--
INSERT INTO `sales` VALUES
(1,'Apples',5,1.20,6.00),
--
INSERT INTO `address` VALUES
(1,'Customer 11 SE');
--
INSERT INTO `sales` VALUES
(1,'Oranges',2,1.70,3.40),
--
INSERT INTO `address` VALUES
(1,'Customer 20 AG');
--
INSERT INTO `sales` VALUES
(1,'Oranges',2,1.70,3.40),
--
INSERT INTO `address` VALUES
(1,'Customer 21 GmbH');
--
INSERT INTO `sales` VALUES
(1,'Oranges',2,1.70,3.40),
--
INSERT INTO `address` VALUES
(1,'Customer 30 GmbH');
--
INSERT INTO `sales` VALUES
(1,'Pickles',2,2.20,4.40),

In MaxScale 23.08.4 war ein ziemlich übler Bug drin: Ein Rückgabewert von 0 aber keine Daten im Backup!!! Siehe dazu auch die Tickets: MXS-4966: mariadb-dump gets an error dumping schemas und MXS-4947: Tables in information_schema are treated as a normal tables. Symptome des Bugs sehen wie folgt aus:

Error: Couldn't read status information for table address ()
Error: Couldn't read status information for table sales ()

Daher empfiehlt sich dringend ein Upgrade auf MaxScale 23.08.5.

Komplexere Applikations-Tests

Wir haben noch einen etwas komplexeren Test erstellt (./sharding_test.php), der folgen Queries abarbeitet:

SET NAMES utf8mb4
SHOW DATABASES
use customer_<nnnn>
START TRANSACTION;
SELECT MIN(id) AS first, MAX(id) AS last FROM `sales`
INSERT INTO sales (id, product, sales, amount, total_amount) VALUES (%d, '%s', %f, %f, %f)
INSERT INTO sales (id, product, sales, amount, total_amount) VALUES (%d, '%s', %f, %f, %f)
UPDATE sales SET product = 'Prepare to delete' WHERE id = %d
DELETE FROM sales WHERE id = %d
COMMIT

Dieser Test lief einwandfrei durch. Die dazu gehörende Kontroll-Abfrage:

SQL> SELECT * FROM customer_0021.sales WHERE id >= (SELECT MAX(id) - 10 FROM customer_0021.sales);

Verschiedene Last-Szenarien können zusätzlich mit db_bench oder dem Acronis perfkit getestet werden. Weitere Informationen dazu siehe hier.

Cross-Shard-Tests

Allensfalls könnte man auf die Idee kommen, Cross-Shard-Queries auszuführen. Dies wird NICHT funktionieren, was ja nicht wirklich erstaunen sollte, da erstens nicht ganz einfach zu implementieren und zweites hier beschrieben:

"Note: As the sharding solution in MaxScale is relatively simple, cross-database queries between two or more shards are not supported."

Quelle: Simple Sharding with Two Servers

und

"USE db1 is routed to the server with db1. If the database is divided to multiple servers, only one server will get the command."

Quelle: SchemaRouter

Hier ein Test mit UNION:

SQL> use customer_0030
Database changed
SQL> SELECT * FROM customer_0020.sales UNION SELECT * FROM customer_0030.sales;
ERROR 1146 (42S02): Table 'customer_0020.sales' doesn't exist

Und hier noch der Gegenbeweis:

SQL> use customer_0020
Database changed
SQL> SELECT * FROM customer_0020.sales UNION SELECT * FROM customer_0030.sales;
ERROR 1146 (42S02): Table 'customer_0030.sales' doesn't exist

Und hier noch den Test mit JOIN:

SQL> use customer_0020
SQL> SELECT *
  FROM customer_0020.sales a
  JOIN customer_0030.sales b ON a.id = b.id
WHERE a.sales > 1
;
ERROR 1146 (42S02): Table 'customer_0030.sales' doesn't exist

SQL> use customer_0030
SQL> SELECT *
  FROM customer_0020.sales a
  JOIN customer_0030.sales b ON a.id = b.id
WHERE a.sales > 1
;
ERROR 1146 (42S02): Table 'customer_0020.sales' doesn't exist

Betrieb eines MaxScale Sharding-Systems

In diesem Kapitel besprechen wir einige Punkte die für den Betrieb eines MariaDB MaxScale Sharding-Systems nützlich sein können.

Do-on-all-shards

Da es immer wieder vorkommen kann, dass O/S oder Datenbank Operationen auf allen Shards ausgeführt werden müssen, wäre es sicher sinnvoll ein Skript zu erstellen, welches reihum, auf allen Shards, den selben Befehl ausführt:

shell> ./do-on-all-shards.sh --sql='SHOW DATABASES'

Ein so geartetes Skript dürfte die Fehlerrate im Betrieb stark reduzieren. Auch Operationen wie das Re-sharding eines Mandanten, wie weiter unten beschrieben, werden sinnvollerweise geskriptet und zentral ausgeführt (MXS-5029).

Invalidieren des Database Map Caches

Mit dem Befehlt invalidate kann man den Database Map Cache des MariaDB MaxScale SchemaRouters invalidieren. Dies gibt uns die Möglichkeit, nach dem Hinzufügen oder dem Entfernen von Mandanten den Cache schnell wieder auf einen aktuellen Stand zu bringen.

shell> maxctrl call command schemarouter invalidate Sharded-Service
OK

Im unterschied zum Befehl invalidate, bei welchem die Einträge nach dem nächsten refresh_intervall auf den neusten Stand gebracht werden, löscht der Befehl clear die Einträge und ein Remap wird sofort ausgeführt.

Wenn man den Database Map Cache von remote mit einem REST API Call invalidieren möchte, geht das wie folgt:

shell> curl -i -X POST -u api_admin:secret http://10.139.158.211:8989/v1/maxscale/modules/schemarouter/clear?Sharded-Service
HTTP/1.1 204 No Content
Connection: close
Date: Mon, 18 Mar 24 11:49:58 GMT
X-Frame-Options: Deny
X-XSS-Protection: 1
Referrer-Policy: same-origin
Cache-Control: no-cache

Quellen:


Wie ändert man SchemaRouter Variablen dynamisch?

Das refresh_interval spezifiziert die Lebensdauer der Einträge im SchemaRouter Database Map Cache. Der default Wert ist 300 s (5 min). Refresh Interval ist daher, meiner Meinung nach, ein unglücklicher Begriff da es nicht das Intervall zwischen zwei Mappings definiert sondern die Lebzeit der Cache-Einträge (livetime?, timeout?). Sobald der Eintrag gelöscht wurde wir ein neuer Refresh der "Database Map" auf jedem Shard getriggert. Der Befehl sieht aktuell wie folgt aus:

SELECT LOWER(t.table_schema), LOWER(t.table_name) FROM information_schema.tables t
 UNION ALL
SELECT LOWER(s.schema_name), '' FROM information_schema.schemata s

So wie es aussieht reicht ein simpler Connect um den Refresh der Database Map zu triggern.

Der aktuelle Wert für refresh_intervall kann wie folgt abgefragt werden.

shell> maxctrl show service Sharded-Service | grep refresh_interval | awk -F'│' '{ print $3 }'
     "refresh_interval": "300000ms",

Um den Wert dynamisch zu ändern hilft folgender Befehl:

shell> MAXCTRL_WARNINGS=0 maxctrl alter service Sharded-Service refresh_interval=10s
OK

Der Wert sollte nicht zu klein eingestellt werden, da während des Mapping Vorgangs alle anderen Connections angehalten werden.

Quellen:


Hinzufügen und Entfernen eines Mandanten

Das Hinzufügen eines neuen Mandanten zu einem Shard stellt kein grosses Problem dar:

SQL> CREATE DATABASE customer_0029;
SQL> use customer_0029
SQL> CREATE TABLE address LIKE customer_template.address;
SQL> CREATE TABLE sales LIKE customer_template.sales;

shell> maxctrl call command schemarouter invalidate Sharded-Service
OK

Das Entfernen eines Mandanten von einem Shard ist hingegen etwas komplizierter und muss in Absprache mit der Applikation erfolgen:

SQL> DROP DATABASE customer_0011;

shell> ./sharding_test.php
.....ERROR: Table 'customer_0011.sales' doesn't exist...ERROR: Unknown database 'customer_0011'.ERROR: Unknown database 'customer_0011'......ERROR: Unknown database 'customer_0011'...

shell> maxctrl call command schemarouter clear Sharded-Service
OK

Zumindest ist mir bisher noch keine schlauere Variante eingefallen. Siehe auch Umziehen eines Mandanten weiter unten.

Umziehen eines Mandanten

Die Kombination von Hinzufügen und Entfernen wäre dann das Umziehen eines Mandanten von einem Shard auf ein anderes Shard, auch re-sharding genannt. Hierzu muss ebenfalls wieder mit der Applikation zusammen eine konzertierte Aktion geplant werden.

Falls dies nicht möglich ist, kann zumindest die Zeit, welche die Applikation Fehler erhält reduziert werden... Folgendes Vorgehen kann verwendet werden um einen Mandanten von Shard 2 auf Shard 3 umzuziehen:

SQL> use customer_0020; LOCK TABLES address READ, sales READ;   -- Auf Shard 2, Applikation wir allenfalls blockiert!

shell> mariadb-dump --user=app --password=secret --host=10.139.158.1 --port=3364 --single-transaction --skip-add-locks --databases customer_0020 | mariadb --user=app --password=secret --host=10.139.158.1 --port=3365   # Kopieren des Mandanten 20 von Shard 2 auf Shard 3

SQL> DROP DATABASE customer_0020;   -- Löschen von Mandant 20 geht nicht!
ERROR 1192 (HY000): Can't execute the given command because you have active locked tables or an active transaction

SQL> UNLOCK TABLES; DROP DATABASE customer_0020;   # So geht das Löschen von Mandant 20.

shell> maxctrl call command schemarouter clear Sharded-Service   # MaxScale Database Map aktualisieren. Schnell machen!!!

Bis zum Refresh der Database Map kann es zu folgenden Fehlern kommen:
error  : (47621) [schemarouter] (Sharded-Service); 'customer_0020.' found on servers 'shard2','shard3' for user 'app'@'10.139.158.1'.
error  : (47621) [schemarouter] (Sharded-Service); 'customer_0020.address' found on servers 'shard2','shard3' for user 'app'@'10.139.158.1'.
error  : (47621) [schemarouter] (Sharded-Service); 'customer_0020.sales' found on servers 'shard2','shard3' for user 'app'@'10.139.158.1'.
error  : (47621) [schemarouter] (Sharded-Service); Duplicate tables found, closing session.

Und applikationsseitig zu:

ERROR: Error: duplicate tables found on two different shards

Hinzufügen oder entfernen eines Shards

Das Umziehen eines Mandanten von einem Shard auf ein anderes Shard ist das kleine re-sharding. Etwas komplexer wird es, wenn man neue Shards hinzufügen oder alte Shards entfernen möchte. Im Anschluss daran (nach dem Hinzufügen bzw. vor dem Entfernen) würde dann ein grosses re-sharding erfolgen. Zuerst das Erweitern des Clusters um ein Shard:

shell> maxctrl list servers
┌────────┬──────────────┬──────┬─────────────┬─────────┬───────────────┬──────────────────┐
│ Server │ Address      │ Port │ Connections │ State   │ GTID          │ Monitor          │
├────────┼──────────────┼──────┼─────────────┼─────────┼───────────────┼──────────────────┤
│ shard1 │ 10.139.158.1 │ 3363 │ 0           │ Running │ 0-3363-26014  │ Sharding-Monitor │
├────────┼──────────────┼──────┼─────────────┼─────────┼───────────────┼──────────────────┤
│ shard2 │ 10.139.158.1 │ 3364 │ 0           │ Running │ 0-3364-240612 │ Sharding-Monitor │
├────────┼──────────────┼──────┼─────────────┼─────────┼───────────────┼──────────────────┤
│ shard3 │ 10.139.158.1 │ 3365 │ 0           │ Running │ 0-3365-289873 │ Sharding-Monitor │
└────────┴──────────────┴──────┴─────────────┴─────────┴───────────────┴──────────────────┘

Das vorbereitete Shard wird MaxScale bekannt gemacht:

shell> maxctrl create server shard4 10.139.158.1 3366
OK

shell> maxctrl list servers
┌────────┬──────────────┬──────┬─────────────┬─────────┬──────────────┬──────────────────┐
│ Server │ Address      │ Port │ Connections │ State   │ GTID         │ Monitor          │
├────────┼──────────────┼──────┼─────────────┼─────────┼──────────────┼──────────────────┤
│ shard1 │ 10.139.158.1 │ 3363 │ 1           │ Running │ 0-3363-23676 │ Sharding-Monitor │
├────────┼──────────────┼──────┼─────────────┼─────────┼──────────────┼──────────────────┤
│ shard2 │ 10.139.158.1 │ 3364 │ 1           │ Running │ 0-3364-52321 │ Sharding-Monitor │
├────────┼──────────────┼──────┼─────────────┼─────────┼──────────────┼──────────────────┤
│ shard3 │ 10.139.158.1 │ 3365 │ 1           │ Running │ 0-3365-39751 │ Sharding-Monitor │
├────────┼──────────────┼──────┼─────────────┼─────────┼──────────────┼──────────────────┤
│ shard4 │ 10.139.158.1 │ 3366 │ 0           │ Down    │              │                  │
└────────┴──────────────┴──────┴─────────────┴─────────┴──────────────┴──────────────────┘

Dann wird des neue Shard mit dem MaxScale Monitor und dem Service verknüpft:

shell> MAXCTRL_WARNINGS=0 maxctrl link monitor Sharding-Monitor shard4
OK

shell> MAXCTRL_WARNINGS=0 maxctrl link service Sharded-Service shard4
OK

shell> maxctrl list servers
┌────────┬──────────────┬──────┬─────────────┬─────────┬──────────────┬──────────────────┐
│ Server │ Address      │ Port │ Connections │ State   │ GTID         │ Monitor          │
├────────┼──────────────┼──────┼─────────────┼─────────┼──────────────┼──────────────────┤
│ shard1 │ 10.139.158.1 │ 3363 │ 1           │ Running │ 0-3363-24961 │ Sharding-Monitor │
├────────┼──────────────┼──────┼─────────────┼─────────┼──────────────┼──────────────────┤
│ shard2 │ 10.139.158.1 │ 3364 │ 1           │ Running │ 0-3364-56215 │ Sharding-Monitor │
├────────┼──────────────┼──────┼─────────────┼─────────┼──────────────┼──────────────────┤
│ shard3 │ 10.139.158.1 │ 3365 │ 1           │ Running │ 0-3365-45177 │ Sharding-Monitor │
├────────┼──────────────┼──────┼─────────────┼─────────┼──────────────┼──────────────────┤
│ shard4 │ 10.139.158.1 │ 3366 │ 1           │ Running │ 0-3366-32    │ Sharding-Monitor │
└────────┴──────────────┴──────┴─────────────┴─────────┴──────────────┴──────────────────┘

Ob dieser zweite Schritt ebenfalls zwingend notwendig ist, wurde nicht untersucht.

Im MariaDB MaxScale Error Log kann man den ganzen Ablauf mitverfolgen:

warning: Discarding journal file '/var/lib/maxscale/Sharding-Monitor_journal.json'. Servers described in the journal are different from the ones configured on the current monitor.
warning: Saving runtime modifications to 'Sharding-Monitor' in '/var/lib/maxscale/maxscale.cnf.d/Sharding-Monitor.cnf'. The modified values will override the values found in the static configuration files.
notice : shard4 sent version string '10.11.7-MariaDB-log'. Detected type: MariaDB, version: 10.11.7.
notice : Server 'shard4' charset: latin1_swedish_ci
notice : Server changed state: shard4[10.139.158.1:3366]: server_up. [Down] -> [Running]
warning: Saving runtime modifications to 'Sharded-Service' in '/var/lib/maxscale/maxscale.cnf.d/Sharded-Service.cnf'. The modified values will override the values found in the static configuration files.
notice : Added 'shard4' to 'Sharded-Service'

Was wir hier nicht vergessen dürfen, ist das neue Shard ebenfalls mit dem Proxy Protokoll auszustatten:

shell> maxctrl show server shard4 | grep proxy
│                     │     "proxy_protocol": false,                 │

MAXCTRL_WARNINGS=0 maxctrl alter server shard4 proxy_protocol=true
OK

Und jetzt können neue Mandanten auf dem neuen Shard hinzugefügt oder alte Mandanten auf das neue Shard umgezogen werden... In unserem Set-up wollen wir alle Mandanten vom Shard 1 auf Shard 4 umziehen und zudem einen neuen Mandanten customer_0040 auf Shard 4 erstellen. Die dazu benötigten Einzelschritte sind oben aufgeführt.

Nachdem das Shard 1 leergeräumt wurde, kann es abgebaut werden:

shell> maxctrl list servers
┌────────┬──────────────┬──────┬─────────────┬─────────┬──────────────┬──────────────────┐
│ Server │ Address      │ Port │ Connections │ State   │ GTID         │ Monitor          │
├────────┼──────────────┼──────┼─────────────┼─────────┼──────────────┼──────────────────┤
│ shard1 │ 10.139.158.1 │ 3363 │ 1           │ Running │ 0-3363-25916 │ Sharding-Monitor │
├────────┼──────────────┼──────┼─────────────┼─────────┼──────────────┼──────────────────┤
│ shard2 │ 10.139.158.1 │ 3364 │ 1           │ Running │ 0-3364-62887 │ Sharding-Monitor │
├────────┼──────────────┼──────┼─────────────┼─────────┼──────────────┼──────────────────┤
│ shard3 │ 10.139.158.1 │ 3365 │ 1           │ Running │ 0-3365-54035 │ Sharding-Monitor │
├────────┼──────────────┼──────┼─────────────┼─────────┼──────────────┼──────────────────┤
│ shard4 │ 10.139.158.1 │ 3366 │ 1           │ Running │ 0-3366-2247  │ Sharding-Monitor │
└────────┴──────────────┴──────┴─────────────┴─────────┴──────────────┴──────────────────┘

Mit dem Befehl destroy server wir ein Shard gelöscht. Bevor das aber funktioniert muss ein Shard aus dem Monitor und dem Service entfernt werden:

shell> MAXCTRL_WARNINGS=0 maxctrl unlink service Sharded-Service shard1
OK

shell> MAXCTRL_WARNINGS=0 maxctrl unlink monitor Sharding-Monitor shard1
OK

shell> maxctrl list servers
┌────────┬──────────────┬──────┬─────────────┬─────────┬──────────────┬──────────────────┐
│ Server │ Address      │ Port │ Connections │ State   │ GTID         │ Monitor          │
├────────┼──────────────┼──────┼─────────────┼─────────┼──────────────┼──────────────────┤
│ shard1 │ 10.139.158.1 │ 3363 │ 0           │ Running │              │                  │
├────────┼──────────────┼──────┼─────────────┼─────────┼──────────────┼──────────────────┤
│ shard2 │ 10.139.158.1 │ 3364 │ 1           │ Running │ 0-3364-64394 │ Sharding-Monitor │
├────────┼──────────────┼──────┼─────────────┼─────────┼──────────────┼──────────────────┤
│ shard3 │ 10.139.158.1 │ 3365 │ 1           │ Running │ 0-3365-56072 │ Sharding-Monitor │
├────────┼──────────────┼──────┼─────────────┼─────────┼──────────────┼──────────────────┤
│ shard4 │ 10.139.158.1 │ 3366 │ 1           │ Running │ 0-3366-3267  │ Sharding-Monitor │
└────────┴──────────────┴──────┴─────────────┴─────────┴──────────────┴──────────────────┘

Wenn das Shard aus dem Monitor und dem Service herausgelöst ist, kann es anschliessend gelöscht werden:

shell> maxctrl destroy server shard1
Warning: Object 'shard1' is defined in a static configuration file and cannot be permanently deleted. If MaxScale is restarted, the object will appear again.
To hide these warnings, run:

    export MAXCTRL_WARNINGS=0

OK
shell> maxctrl list servers
┌────────┬──────────────┬──────┬─────────────┬─────────┬──────────────┬──────────────────┐
│ Server │ Address      │ Port │ Connections │ State   │ GTID         │ Monitor          │
├────────┼──────────────┼──────┼─────────────┼─────────┼──────────────┼──────────────────┤
│ shard2 │ 10.139.158.1 │ 3364 │ 1           │ Running │ 0-3364-65018 │ Sharding-Monitor │
├────────┼──────────────┼──────┼─────────────┼─────────┼──────────────┼──────────────────┤
│ shard3 │ 10.139.158.1 │ 3365 │ 1           │ Running │ 0-3365-56886 │ Sharding-Monitor │
├────────┼──────────────┼──────┼─────────────┼─────────┼──────────────┼──────────────────┤
│ shard4 │ 10.139.158.1 │ 3366 │ 1           │ Running │ 0-3366-3648  │ Sharding-Monitor │
└────────┴──────────────┴──────┴─────────────┴─────────┴──────────────┴──────────────────┘

Und im MaxScale Error Log kann man die Änderungen schön mitverfolgen:

notice : Removed 'shard1' from 'Sharded-Service'
warning: Discarding journal file '/var/lib/maxscale/Sharding-Monitor_journal.json'. Servers described in the journal are different from the ones configured on the current monitor.
notice : Destroyed server 'shard1' at 10.139.158.1:3363

Wichtig: Mir wurde mitgeteilt, dass mit destroy server --force die unlink service und unlink monitor Befehle durch MaxScale automatisch ausgeführt werden.

Quelle:


Anpassen der Konfigurationsdateien

Bei den oben beschriebenen Shard Operationen habe wir einige Warnungen erhalten:

Warning: Object 'shard1' is defined in a static configuration file and cannot be permanently deleted. If MaxScale is restarted, the object will appear again.

und

Warning: Saving runtime modifications to 'Sharding-Monitor' in '/var/lib/maxscale/maxscale.cnf.d/Sharding-Monitor.cnf'. The modified values will override the values found in the static configuration files.

Die entsprechenden Konfigurationsdateien werden von MaxScale automatisch bei dynamischen System-Änderungen erstellt:

shell> ll /var/lib/maxscale/maxscale.cnf.d/ /etc/maxscale.cnf
-rw-r--r-- 1 root     root      612 Feb 13 14:23 /etc/maxscale.cnf

/var/lib/maxscale/maxscale.cnf.d/:
total 12
-rw------- 1 maxscale maxscale 187 Feb 13 16:08 Sharding-Monitor.cnf
-rw------- 1 maxscale maxscale 150 Feb 13 16:07 Sharded-Service.cnf
-rw------- 1 maxscale maxscale  52 Feb 13 15:46 shard4.cnf

cat /var/lib/maxscale/maxscale.cnf.d/*
[Sharded-Service]
debug=true
refresh_interval=10000ms
auth_all_servers=true
log_debug=true
password=secret
router=schemarouter
type=service
user=maxscale_admin
targets=shard2,shard3,shard4

[Sharding-Monitor]
module=galeramon
monitor_interval=1000ms
password=secret
servers=shard2,shard3,shard4
type=monitor
user=maxscale_monitor

[shard4]
address=10.139.158.1
port=3366
type=server

Es müssen also noch entsprechende Nachbesserungen an den Konfigurationsdateien vorgenommen werden. Man müsste sich allgemein überlegen ob man bei einem hochdynamischen System nicht alles dynamisch über Befehle konfigurieren sollte...

Wartungsarbeiten am Shard

Wenn für Wartungsarbeiten ein Shard offline genommen werden soll, hier im Beispiel shard2, kann dies wie folgt bewerkstelligt werden:

shell> maxctrl list servers
┌────────┬──────────────┬──────┬─────────────┬─────────┬──────────────┬──────────────────┐
│ Server │ Address      │ Port │ Connections │ State   │ GTID         │ Monitor          │
├────────┼──────────────┼──────┼─────────────┼─────────┼──────────────┼──────────────────┤
│ shard2 │ 10.139.158.1 │ 3364 │ 1           │ Running │ 0-3364-69817 │ Sharding-Monitor │
├────────┼──────────────┼──────┼─────────────┼─────────┼──────────────┼──────────────────┤
│ shard3 │ 10.139.158.1 │ 3365 │ 1           │ Running │ 0-3365-63166 │ Sharding-Monitor │
├────────┼──────────────┼──────┼─────────────┼─────────┼──────────────┼──────────────────┤
│ shard4 │ 10.139.158.1 │ 3366 │ 1           │ Running │ 0-3366-6902  │ Sharding-Monitor │
└────────┴──────────────┴──────┴─────────────┴─────────┴──────────────┴──────────────────┘

shell> maxctrl set server shard2 drain
OK

shell> maxctrl set server shard2 maintenance
OK

shell> maxctrl list servers
┌────────┬──────────────┬──────┬─────────────┬──────────────────────┬───────────────┬──────────────────┐
│ Server │ Address      │ Port │ Connections │ State                │ GTID          │ Monitor          │
├────────┼──────────────┼──────┼─────────────┼──────────────────────┼───────────────┼──────────────────┤
│ shard2 │ 10.139.158.1 │ 3364 │ 0           │ Maintenance, Running │ 0-3364-240612 │ Sharding-Monitor │
├────────┼──────────────┼──────┼─────────────┼──────────────────────┼───────────────┼──────────────────┤
│ shard3 │ 10.139.158.1 │ 3365 │ 0           │ Running              │ 0-3365-289873 │ Sharding-Monitor │
├────────┼──────────────┼──────┼─────────────┼──────────────────────┼───────────────┼──────────────────┤
│ shard4 │ 10.139.158.1 │ 3366 │ 0           │ Running              │ 0-3366-119848 │ Sharding-Monitor │
└────────┴──────────────┴──────┴─────────────┴──────────────────────┴───────────────┴──────────────────┘

Zu diesem Zeitpunkt können die Wartungsarbeiten an der Maschine oder der Datenbank vorgenommen werden...

Anschliessend müssen BEIDE Stati wieder gecleared werden, sofern beide gesetzt wurden (MXS-5028):

shell> maxctrl clear server shard2 maintenance
OK

shell> maxctrl clear server shard2 drain
OK

maxctrl list servers
┌────────┬──────────────┬──────┬─────────────┬─────────┬───────────────┬──────────────────┐
│ Server │ Address      │ Port │ Connections │ State   │ GTID          │ Monitor          │
├────────┼──────────────┼──────┼─────────────┼─────────┼───────────────┼──────────────────┤
│ shard2 │ 10.139.158.1 │ 3364 │ 0           │ Running │ 0-3364-240612 │ Sharding-Monitor │
├────────┼──────────────┼──────┼─────────────┼─────────┼───────────────┼──────────────────┤
│ shard3 │ 10.139.158.1 │ 3365 │ 0           │ Running │ 0-3365-289873 │ Sharding-Monitor │
├────────┼──────────────┼──────┼─────────────┼─────────┼───────────────┼──────────────────┤
│ shard4 │ 10.139.158.1 │ 3366 │ 0           │ Running │ 0-3366-119848 │ Sharding-Monitor │
└────────┴──────────────┴──────┴─────────────┴─────────┴───────────────┴──────────────────┘

Der Unterschied zwischen drain und maintenance besteht darin, dass bei drain keinen neuen Verbindungen mehr auf das Shard zugelassen werden aber bei bestehenden Verbindungen wird gewartet, bis sie geschlossen werden. Bei maintenance werden die Verbindungen sofort zwangsweise terminiert.

Beobachtung / Observierung eines MariaDB MaxScale Sharding-Systems

Mit dem MaxScale CLI Client maxtrl kann man den Zustand des MariaDB MaxScale Load Balancers abfragen hierzu gibt es zahlreiche Befehle, hauptsächlich list und show:

shell> maxctrl show module schemarouter | head -n 12
┌─────────────┬────────────────────────────────────────────────┐
│ Module      │ schemarouter                                   │
├─────────────┼────────────────────────────────────────────────┤
│ Type        │ Router                                         │
├─────────────┼────────────────────────────────────────────────┤
│ Version     │ V1.0.0                                         │
├─────────────┼────────────────────────────────────────────────┤
│ Maturity    │ Beta                                           │
├─────────────┼────────────────────────────────────────────────┤
│ Description │ A database sharding router for simple sharding │
├─────────────┼────────────────────────────────────────────────┤
│ Parameters  │ ...                                            │

shell> maxctrl list servers
┌────────┬──────────────┬──────┬─────────────┬─────────┬───────────────┬──────────────────┐
│ Server │ Address      │ Port │ Connections │ State   │ GTID          │ Monitor          │
├────────┼──────────────┼──────┼─────────────┼─────────┼───────────────┼──────────────────┤
│ shard2 │ 10.139.158.1 │ 3364 │ 4           │ Running │ 0-3364-290859 │ Sharding-Monitor │
├────────┼──────────────┼──────┼─────────────┼─────────┼───────────────┼──────────────────┤
│ shard3 │ 10.139.158.1 │ 3365 │ 4           │ Running │ 0-3365-322671 │ Sharding-Monitor │
├────────┼──────────────┼──────┼─────────────┼─────────┼───────────────┼──────────────────┤
│ shard4 │ 10.139.158.1 │ 3366 │ 4           │ Running │ 0-3366-140018 │ Sharding-Monitor │
└────────┴──────────────┴──────┴─────────────┴─────────┴───────────────┴──────────────────┘

Die Information für die Spalte Connections ist verwirrend, da wir bei diesem Sharding-System in diesem Fall auf jedem Shard nur 1, 1 und 2 Verbindungen offen haben.

Wenn man sich mit SHOW PROCESSLIST die Situation aber auf dem jeweiligen Shard anschaut, sieht man, dass MaxScale auf JEDEM Shard für jede eingehende Verbindung auch eine Verbindung auf jedes Shard aufbaut. Somit ist die Anzeige oben eigentlich technisch korrekt, nur nicht, was man erwarten würde:

SQL> SHOW PROCESSLIST;
+--------+------------------+----------------------+---------------+---------+------+----------+-----------------------------------------------------------------+----------+
| Id     | User             | Host                 | db            | Command | Time | State    | Info                                                            | Progress |
+--------+------------------+----------------------+---------------+---------+------+----------+-----------------------------------------------------------------+----------+
|    123 | root             | localhost            | customer_0021 | Query   |    0 | starting | show processlist                                                |    0.000 |
|  68107 | maxscale_monitor | 10.139.158.211:35418 | NULL          | Sleep   |    0 |          | NULL                                                            |    0.000 |
| 113372 | app              | 10.139.158.1:47548   | NULL          | Sleep   |   47 |          | NULL                                                            |    0.000 |
| 113538 | app              | 10.139.158.1:49058   | NULL          | Sleep   |   41 |          | NULL                                                            |    0.000 |
| 113662 | app              | 10.139.158.1:47072   | NULL          | Sleep   |   37 |          | NULL                                                            |    0.000 |
| 114789 | app              | 10.139.158.1:39574   | customer_0022 | Query   |    0 | Updating | UPDATE sales SET product = 'Prepare to delete' WHERE id = 15622 |    0.000 |
+--------+------------------+----------------------+---------------+---------+------+----------+-----------------------------------------------------------------+----------+

Das skaliert so nicht bei grossen Systemen mit hunderten oder tausenden von Mandanten! Ev. kommt in diesem Fall das MariaDB Thread Pool Feature zum Einsatz.

Laut dem MaxScale Entwickler ist dies erwartetes Verhalten... (MXS-4977)

shell> maxctrl list services
┌─────────────────┬──────────────┬─────────────┬───────────────────┬────────────────────────┐
│ Service         │ Router       │ Connections │ Total Connections │ Targets                │
├─────────────────┼──────────────┼─────────────┼───────────────────┼────────────────────────┤
│ Sharded-Service │ schemarouter │ 4           │ 82776             │ shard2, shard3, shard4 │
└─────────────────┴──────────────┴─────────────┴───────────────────┴────────────────────────┘

shell> maxctrl list listeners
┌──────────────────────────┬──────┬──────┬─────────┬─────────────────┐
│ Name                     │ Port │ Host │ State   │ Service         │
├──────────────────────────┼──────┼──────┼─────────┼─────────────────┤
│ Sharded-Service-Listener │ 3306 │ ::   │ Running │ Sharded-Service │
└──────────────────────────┴──────┴──────┴─────────┴─────────────────┘

shell> maxctrl list monitors
┌──────────────────┬─────────┬────────────────────────┐
│ Monitor          │ State   │ Servers                │
├──────────────────┼─────────┼────────────────────────┤
│ Sharding-Monitor │ Running │ shard2, shard3, shard4 │
└──────────────────┴─────────┴────────────────────────┘

shell> maxctrl show server shard2 | head -n 20
┌─────────────────────┬──────────────────────────────────────────────┐
│ Server              │ shard2                                       │
├─────────────────────┼──────────────────────────────────────────────┤
│ Source              │ /etc/maxscale.cnf                            │
├─────────────────────┼──────────────────────────────────────────────┤
│ Address             │ 10.139.158.1                                 │
├─────────────────────┼──────────────────────────────────────────────┤
│ Port                │ 3364                                         │
├─────────────────────┼──────────────────────────────────────────────┤
│ State               │ Running                                      │
├─────────────────────┼──────────────────────────────────────────────┤
│ Version             │ 10.11.7-MariaDB-log                          │
├─────────────────────┼──────────────────────────────────────────────┤
│ Uptime              │ 178960                                       │
├─────────────────────┼──────────────────────────────────────────────┤
│ Last Event          │ server_down                                  │
├─────────────────────┼──────────────────────────────────────────────┤
│ Triggered At        │ Sun, 04 Feb 2024 07:37:17 GMT                │
├─────────────────────┼──────────────────────────────────────────────┤
│ Services            │ Sharded-Service                              │
├─────────────────────┼──────────────────────────────────────────────┤
│ Monitors            │ Sharding-Monitor                             │
├─────────────────────┼──────────────────────────────────────────────┤
...
├─────────────────────┼──────────────────────────────────────────────┤
│ Current Connections │ 5                                            │
├─────────────────────┼──────────────────────────────────────────────┤
│ Total Connections   │ 27                                           │
├─────────────────────┼──────────────────────────────────────────────┤
│ Max Connections     │ 5                                            │

shell> maxctrl show service Sharded-Service
┌─────────────────────┬──────────────────────────────────────────────────────┐
│ Service             │ Sharded-Service                                      │
├─────────────────────┼──────────────────────────────────────────────────────┤
│ Source              │ /var/lib/maxscale/maxscale.cnf.d/Sharded-Service.cnf │
├─────────────────────┼──────────────────────────────────────────────────────┤
│ Router              │ schemarouter                                         │
├─────────────────────┼──────────────────────────────────────────────────────┤
│ State               │ Started                                              │
├─────────────────────┼──────────────────────────────────────────────────────┤
│ Started At          │ 3/18/2024, 1:52:30 PM                                │
├─────────────────────┼──────────────────────────────────────────────────────┤
│ Users Loaded At     │ 3/18/2024, 1:52:30 PM                                │
├─────────────────────┼──────────────────────────────────────────────────────┤
│ Current Connections │ 4                                                    │
├─────────────────────┼──────────────────────────────────────────────────────┤
│ Total Connections   │ 84590                                                │
├─────────────────────┼──────────────────────────────────────────────────────┤
│ Max Connections     │ 5                                                    │
├─────────────────────┼──────────────────────────────────────────────────────┤
│ Cluster             │                                                      │
├─────────────────────┼──────────────────────────────────────────────────────┤
│ Servers             │ shard2                                               │
│                     │ shard3                                               │
│                     │ shard4                                               │
├─────────────────────┼──────────────────────────────────────────────────────┤
│ Services            │                                                      │
├─────────────────────┼──────────────────────────────────────────────────────┤
│ Filters             │                                                      │
├─────────────────────┼──────────────────────────────────────────────────────┤
│ Parameters          │ {                                                    │
│                     │     "auth_all_servers": true,                        │
│                     │     "connection_keepalive": "300000ms",              │
│                     │     "debug": true,                                   │
│                     │     "disable_sescmd_history": false,                 │
│                     │     "enable_root_user": false,                       │
│                     │     "force_connection_keepalive": false,             │
│                     │     "idle_session_pool_time": "-1ms",                │
│                     │     "ignore_tables": [],                             │
│                     │     "ignore_tables_regex": null,                     │
│                     │     "localhost_match_wildcard_host": true,           │
│                     │     "log_auth_warnings": true,                       │
│                     │     "log_debug": true,                               │
│                     │     "log_info": false,                               │
│                     │     "log_notice": false,                             │
│                     │     "log_warning": false,                            │
│                     │     "max_connections": 0,                            │
│                     │     "max_sescmd_history": 50,                        │
│                     │     "max_staleness": "150000ms",                     │
│                     │     "multiplex_timeout": "60000ms",                  │
│                     │     "net_write_timeout": "0ms",                      │
│                     │     "password": "*****",                             │
│                     │     "prune_sescmd_history": true,                    │
│                     │     "rank": "primary",                               │
│                     │     "refresh_databases": false,                      │
│                     │     "refresh_interval": "10000ms",                   │
│                     │     "retain_last_statements": -1,                    │
│                     │     "router": "schemarouter",                        │
│                     │     "session_trace": false,                          │
│                     │     "strip_db_esc": true,                            │
│                     │     "type": "service",                               │
│                     │     "user": "maxscale_admin",                        │
│                     │     "user_accounts_file": null,                      │
│                     │     "user_accounts_file_usage": "add_when_load_ok",  │
│                     │     "version_string": null,                          │
│                     │     "wait_timeout": "0ms"                            │
│                     │ }                                                    │
├─────────────────────┼──────────────────────────────────────────────────────┤
│ Router Diagnostics  │ {                                                    │
│                     │     "average_session": 0.028822357131634554,         │
│                     │     "longest_sescmd_chain": 4,                       │
│                     │     "longest_session": 50,                           │
│                     │     "queries": 761134,                               │
│                     │     "sescmd_percentage": 44.44342257736483,          │
│                     │     "shard_map_hits": 84356,                         │
│                     │     "shard_map_misses": 5,                           │
│                     │     "shard_map_stale": 229,                          │
│                     │     "shard_map_updates": 216,                        │
│                     │     "shortest_session": 0,                           │
│                     │     "times_sescmd_limit_exceeded": 0                 │
│                     │ }                                                    │
└─────────────────────┴──────────────────────────────────────────────────────┘

Siehe hierzu auch MaxScale SchemaRouter Router diagnostics.

shell> maxctrl show monitor Sharding-Monitor
┌─────────────────────┬──────────────────────────────────────────────────────────┐
│ Monitor             │ Sharding-Monitor                                         │
├─────────────────────┼──────────────────────────────────────────────────────────┤
│ Source              │ /etc/maxscale.cnf                                        │
├─────────────────────┼──────────────────────────────────────────────────────────┤
│ Module              │ galeramon                                                │
├─────────────────────┼──────────────────────────────────────────────────────────┤
│ State               │ Running                                                  │
├─────────────────────┼──────────────────────────────────────────────────────────┤
│ Servers             │ shard1                                                   │
│                     │ shard2                                                   │
│                     │ shard3                                                   │
├─────────────────────┼──────────────────────────────────────────────────────────┤
│ Parameters          │ {                                                        │
│                     │     "available_when_donor": false,                       │
│                     │     "backend_connect_attempts": 1,                       │
│                     │     "backend_connect_timeout": "3000ms",                 │
│                     │     "backend_read_timeout": "3000ms",                    │
│                     │     "backend_write_timeout": "3000ms",                   │
│                     │     "disable_master_failback": false,                    │
│                     │     "disable_master_role_setting": false,                │
│                     │     "disk_space_check_interval": "0ms",                  │
│                     │     "disk_space_threshold": null,                        │
│                     │     "events": "all,master_down,master_up,...,new_donor", │
│                     │     "journal_max_age": "28800000ms",                     │
│                     │     "module": "galeramon",                               │
│                     │     "monitor_interval": "1000ms",                        │
│                     │     "password": "*****",                                 │
│                     │     "root_node_as_master": false,                        │
│                     │     "script": null,                                      │
│                     │     "script_timeout": "90000ms",                         │
│                     │     "set_donor_nodes": false,                            │
│                     │     "type": "monitor",                                   │
│                     │     "use_priority": false,                               │
│                     │     "user": "maxscale_monitor"                           │
│                     │ }                                                        │
├─────────────────────┼──────────────────────────────────────────────────────────┤
│ Monitor Diagnostics │ {                                                        │
│                     │     "disable_master_failback": false,                    │
│                     │     "disable_master_role_setting": false,                │
│                     │     "root_node_as_master": false,                        │
│                     │     "server_info": [                                     │
│                     │         {                                                │
│                     │             "gtid_binlog_pos": "0-3363-26014",           │
│                     │             "gtid_current_pos": "0-3363-26014",          │
│                     │             "master_id": 0,                              │
│                     │             "name": "shard1",                            │
│                     │             "read_only": false,                          │
│                     │             "server_id": 3363                            │
│                     │         },                                               │
│                     │         {                                                │
│                     │             "gtid_binlog_pos": "0-3364-240612",          │
│                     │             "gtid_current_pos": "0-3364-240612",         │
│                     │             "master_id": 0,                              │
│                     │             "name": "shard2",                            │
│                     │             "read_only": false,                          │
│                     │             "server_id": 3364                            │
│                     │         },                                               │
│                     │         {                                                │
│                     │             "gtid_binlog_pos": "0-3365-289873",          │
│                     │             "gtid_current_pos": "0-3365-289873",         │
│                     │             "master_id": 0,                              │
│                     │             "name": "shard3",                            │
│                     │             "read_only": false,                          │
│                     │             "server_id": 3365                            │
│                     │         }                                                │
│                     │     ],                                                   │
│                     │     "set_donor_nodes": false,                            │
│                     │     "use_priority": false                                │
│                     │ }                                                        │
└─────────────────────┴──────────────────────────────────────────────────────────┘

shell> maxctrl list sessions;
┌───────┬──────┬──────────────┬───────────────────────┬───────┬─────────────────┬────────┬──────────────┐
│ Id    │ User │ Host         │ Connected             │ Idle  │ Service         │ Memory │ I/O-Activity │
├───────┼──────┼──────────────┼───────────────────────┼───────┼─────────────────┼────────┼──────────────┤
│ 87240 │ app  │ 10.139.158.1 │ 3/18/2024, 2:33:54 PM │ 0     │ Sharded-Service │ 68644  │ 33           │
├───────┼──────┼──────────────┼───────────────────────┼───────┼─────────────────┼────────┼──────────────┤
│ 72654 │ app  │ 10.139.158.1 │ 3/18/2024, 2:25:27 PM │ 506.3 │ Sharded-Service │ 199328 │ 0            │
├───────┼──────┼──────────────┼───────────────────────┼───────┼─────────────────┼────────┼──────────────┤
│ 72364 │ app  │ 10.139.158.1 │ 3/18/2024, 2:25:18 PM │ 516   │ Sharded-Service │ 199328 │ 0            │
├───────┼──────┼──────────────┼───────────────────────┼───────┼─────────────────┼────────┼──────────────┤
│ 72530 │ app  │ 10.139.158.1 │ 3/18/2024, 2:25:23 PM │ 510.5 │ Sharded-Service │ 199328 │ 0            │
└───────┴──────┴──────────────┴───────────────────────┴───────┴─────────────────┴────────┴──────────────┘

shell> maxctrl show session 26
┌───────────────────────┬───────────────────────────────────────┐
│ Id                    │ 26                                    │
├───────────────────────┼───────────────────────────────────────┤
│ Service               │ Sharded-Service                       │
├───────────────────────┼───────────────────────────────────────┤
│ State                 │ Session started                       │
├───────────────────────┼───────────────────────────────────────┤
│ User                  │ app                                   │
├───────────────────────┼───────────────────────────────────────┤
│ Host                  │ 10.139.158.1                          │
├───────────────────────┼───────────────────────────────────────┤
│ Port                  │ 42854                                 │
├───────────────────────┼───────────────────────────────────────┤
│ Database              │                                       │
├───────────────────────┼───────────────────────────────────────┤
│ Connected             │ 2/4/2024, 9:31:12 AM                  │
├───────────────────────┼───────────────────────────────────────┤
│ Idle                  │ 610.4                                 │
├───────────────────────┼───────────────────────────────────────┤
│ Parameters            │ {                                     │
│                       │     "log_error": false,               │
│                       │     "log_info": false,                │
│                       │     "log_notice": false,              │
│                       │     "log_warning": false              │
│                       │ }                                     │
├───────────────────────┼───────────────────────────────────────┤
│ Client TLS Cipher     │                                       │
├───────────────────────┼───────────────────────────────────────┤
│ Connection attributes │ {                                     │
│                       │     "_client_name": "libmariadb",     │
│                       │     "_client_version": "3.3.8",       │
│                       │     "_os": "Linux",                   │
│                       │     "_pid": "251037",                 │
│                       │     "_platform": "x86_64",            │
│                       │     "_server_host": "10.139.158.211", │
│                       │     "program_name": "mysql"           │
│                       │ }                                     │
├───────────────────────┼───────────────────────────────────────┤
│ Connections           │ shard1                                │
│                       │ shard2                                │
│                       │ shard3                                │
├───────────────────────┼───────────────────────────────────────┤
│ Connection IDs        │ 666                                   │
│                       │ 139                                   │
│                       │ 138                                   │
├───────────────────────┼───────────────────────────────────────┤
│ Queries               │                                       │
├───────────────────────┼───────────────────────────────────────┤
│ Log                   │                                       │
├───────────────────────┼───────────────────────────────────────┤
│ Memory                │ {                                     │
│                       │     "connection_buffers": {           │
│                       │         "backends": {                 │
│                       │             "shard1": {               │
│                       │                 "misc": 678,          │
│                       │                 "readq": 65536,       │
│                       │                 "total": 66214,       │
│                       │                 "writeq": 0           │
│                       │             },                        │
│                       │             "shard2": {               │
│                       │                 "misc": 662,          │
│                       │                 "readq": 0,           │
│                       │                 "total": 662,         │
│                       │                 "writeq": 0           │
│                       │             },                        │
│                       │             "shard3": {               │
│                       │                 "misc": 678,          │
│                       │                 "readq": 65536,       │
│                       │                 "total": 66214,       │
│                       │                 "writeq": 0           │
│                       │             }                         │
│                       │         },                            │
│                       │         "client": {                   │
│                       │             "misc": 654,              │
│                       │             "readq": 65536,           │
│                       │             "total": 66190,           │
│                       │             "writeq": 0               │
│                       │         },                            │
│                       │         "total": 199280               │
│                       │     },                                │
│                       │     "exec_metadata": 0,               │
│                       │     "last_queries": 0,                │
│                       │     "sescmd_history": 48,             │
│                       │     "total": 199328,                  │
│                       │     "variables": 0                    │
│                       │ }                                     │
├───────────────────────┼───────────────────────────────────────┤
│ I/O Activity          │ 0                                     │
└───────────────────────┴───────────────────────────────────────┘

shell> maxctrl show listener Sharded-Service-Listener
┌────────────┬───────────────────────────────────────────┐
│ Name       │ Sharded-Service-Listener                  │
├────────────┼───────────────────────────────────────────┤
│ Source     │ /etc/maxscale.cnf                         │
├────────────┼───────────────────────────────────────────┤
│ Service    │ Sharded-Service                           │
├────────────┼───────────────────────────────────────────┤
│ Parameters │ {                                         │
│            │     "MariaDBProtocol": {                  │
│            │         "allow_replication": true         │
│            │     },                                    │
│            │     "address": "::",                      │
│            │     "authenticator": null,                │
│            │     "authenticator_options": null,        │
│            │     "connection_init_sql_file": null,     │
│            │     "connection_metadata": [              │
│            │         "character_set_client=auto",      │
│            │         "character_set_connection=auto",  │
│            │         "character_set_results=auto",     │
│            │         "max_allowed_packet=auto",        │
│            │         "system_time_zone=auto",          │
│            │         "time_zone=auto",                 │
│            │         "tx_isolation=auto"               │
│            │     ],                                    │
│            │     "port": 3306,                         │
│            │     "protocol": "MariaDBProtocol",        │
│            │     "proxy_protocol_networks": null,      │
│            │     "service": "Sharded-Service",         │
│            │     "socket": null,                       │
│            │     "sql_mode": "default",                │
│            │     "ssl": false,                         │
│            │     "ssl_ca": null,                       │
│            │     "ssl_cert": null,                     │
│            │     "ssl_cert_verify_depth": 9,           │
│            │     "ssl_cipher": null,                   │
│            │     "ssl_crl": null,                      │
│            │     "ssl_key": null,                      │
│            │     "ssl_verify_peer_certificate": false, │
│            │     "ssl_verify_peer_host": false,        │
│            │     "ssl_version": "MAX",                 │
│            │     "type": "listener",                   │
│            │     "user_mapping_file": null             │
│            │ }                                         │
└────────────┴───────────────────────────────────────────┘

shell> maxctrl show module schemarouter
┌─────────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Module      │ schemarouter                                                                                                            │
├─────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Type        │ Router                                                                                                                  │
├─────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Version     │ V1.0.0                                                                                                                  │
├─────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Maturity    │ Beta                                                                                                                    │
├─────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Description │ A database sharding router for simple sharding                                                                          │
├─────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Parameters  │ [                                                                                                                       │
│             │     {                                                                                                                   │
│             │         "default_value": false,                                                                                         │
│             │         "description": "Enable debug mode",                                                                             │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "debug",                                                                                                │
│             │         "type": "bool"                                                                                                  │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "default_value": [],                                                                                            │
│             │         "description": "List of tables to ignore when checking for duplicates",                                         │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "ignore_tables",                                                                                        │
│             │         "type": "stringlist"                                                                                            │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "description": "Regex of tables to ignore when checking for duplicates",                                        │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "ignore_tables_regex",                                                                                  │
│             │         "type": "regex"                                                                                                 │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "default_value": "150000ms",                                                                                    │
│             │         "description": "Maximum allowed staleness of a database map entry before clients block and wait for an update", │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "max_staleness",                                                                                        │
│             │         "type": "duration",                                                                                             │
│             │         "unit": "ms"                                                                                                    │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "default_value": false,                                                                                         │
│             │         "description": "Refresh database mapping information",                                                          │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "refresh_databases",                                                                                    │
│             │         "type": "bool"                                                                                                  │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "default_value": "300000ms",                                                                                    │
│             │         "description": "How often to refresh the database mapping information",                                         │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "refresh_interval",                                                                                     │
│             │         "type": "duration",                                                                                             │
│             │         "unit": "ms"                                                                                                    │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "default_value": false,                                                                                         │
│             │         "description": "Retrieve users from all backend servers instead of only one",                                   │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "auth_all_servers",                                                                                     │
│             │         "type": "bool"                                                                                                  │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "default_value": "300000ms",                                                                                    │
│             │         "description": "How ofted idle connections are pinged",                                                         │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "connection_keepalive",                                                                                 │
│             │         "type": "duration",                                                                                             │
│             │         "unit": "ms"                                                                                                    │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "deprecated": true,                                                                                             │
│             │         "description": "Alias for 'wait_timeout'",                                                                      │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "connection_timeout",                                                                                   │
│             │         "type": "duration"                                                                                              │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "default_value": false,                                                                                         │
│             │         "description": "Disable session command history",                                                               │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "disable_sescmd_history",                                                                               │
│             │         "type": "bool"                                                                                                  │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "default_value": false,                                                                                         │
│             │         "description": "Allow the root user to connect to this service",                                                │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "enable_root_user",                                                                                     │
│             │         "type": "bool"                                                                                                  │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "default_value": false,                                                                                         │
│             │         "description": "Ping connections unconditionally",                                                              │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "force_connection_keepalive",                                                                           │
│             │         "type": "bool"                                                                                                  │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "default_value": "-1ms",                                                                                        │
│             │         "description": "Put connections into pool after session has been idle for this long",                           │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "idle_session_pool_time",                                                                               │
│             │         "type": "duration",                                                                                             │
│             │         "unit": "ms"                                                                                                    │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "default_value": true,                                                                                          │
│             │         "description": "Match localhost to wildcard host",                                                              │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "localhost_match_wildcard_host",                                                                        │
│             │         "type": "bool"                                                                                                  │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "default_value": true,                                                                                          │
│             │         "description": "Log a warning when client authentication fails",                                                │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "log_auth_warnings",                                                                                    │
│             │         "type": "bool"                                                                                                  │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "default_value": false,                                                                                         │
│             │         "description": "Log debug messages for this service (debug builds only)",                                       │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "log_debug",                                                                                            │
│             │         "type": "bool"                                                                                                  │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "default_value": false,                                                                                         │
│             │         "description": "Log info messages for this service",                                                            │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "log_info",                                                                                             │
│             │         "type": "bool"                                                                                                  │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "default_value": false,                                                                                         │
│             │         "description": "Log notice messages for this service",                                                          │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "log_notice",                                                                                           │
│             │         "type": "bool"                                                                                                  │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "default_value": false,                                                                                         │
│             │         "description": "Log warning messages for this service",                                                         │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "log_warning",                                                                                          │
│             │         "type": "bool"                                                                                                  │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "default_value": 0,                                                                                             │
│             │         "description": "Maximum number of connections",                                                                 │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "max_connections",                                                                                      │
│             │         "type": "count"                                                                                                 │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "default_value": 50,                                                                                            │
│             │         "description": "Session command history size",                                                                  │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "max_sescmd_history",                                                                                   │
│             │         "type": "count"                                                                                                 │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "default_value": "60000ms",                                                                                     │
│             │         "description": "How long a session can wait for a connection to become available",                              │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "multiplex_timeout",                                                                                    │
│             │         "type": "duration",                                                                                             │
│             │         "unit": "ms"                                                                                                    │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "default_value": "0ms",                                                                                         │
│             │         "description": "Network write timeout",                                                                         │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "net_write_timeout",                                                                                    │
│             │         "type": "duration",                                                                                             │
│             │         "unit": "ms"                                                                                                    │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "description": "Password for the user used to retrieve database users",                                         │
│             │         "mandatory": true,                                                                                              │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "password",                                                                                             │
│             │         "type": "password"                                                                                              │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "default_value": true,                                                                                          │
│             │         "description": "Prune old session command history if the limit is exceeded",                                    │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "prune_sescmd_history",                                                                                 │
│             │         "type": "bool"                                                                                                  │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "default_value": "primary",                                                                                     │
│             │         "description": "Service rank",                                                                                  │
│             │         "enum_values": [                                                                                                │
│             │             "primary",                                                                                                  │
│             │             "secondary"                                                                                                 │
│             │         ],                                                                                                              │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "rank",                                                                                                 │
│             │         "type": "enum"                                                                                                  │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "default_value": -1,                                                                                            │
│             │         "description": "Number of statements kept in memory",                                                           │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "retain_last_statements",                                                                               │
│             │         "type": "int"                                                                                                   │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "default_value": false,                                                                                         │
│             │         "description": "Enable session tracing for this service",                                                       │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "session_trace",                                                                                        │
│             │         "type": "bool"                                                                                                  │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "default_value": false,                                                                                         │
│             │         "deprecated": true,                                                                                             │
│             │         "description": "Track session state using server responses",                                                    │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "session_track_trx_state",                                                                              │
│             │         "type": "bool"                                                                                                  │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "default_value": true,                                                                                          │
│             │         "deprecated": true,                                                                                             │
│             │         "description": "Strip escape characters from database names",                                                   │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "strip_db_esc",                                                                                         │
│             │         "type": "bool"                                                                                                  │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "description": "Username used to retrieve database users",                                                      │
│             │         "mandatory": true,                                                                                              │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "user",                                                                                                 │
│             │         "type": "string"                                                                                                │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "description": "Load additional users from a file",                                                             │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": false,                                                                                            │
│             │         "name": "user_accounts_file",                                                                                   │
│             │         "type": "path"                                                                                                  │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "default_value": "add_when_load_ok",                                                                            │
│             │         "description": "When and how the user accounts file is used",                                                   │
│             │         "enum_values": [                                                                                                │
│             │             "add_when_load_ok",                                                                                         │
│             │             "file_only_always"                                                                                          │
│             │         ],                                                                                                              │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": false,                                                                                            │
│             │         "name": "user_accounts_file_usage",                                                                             │
│             │         "type": "enum"                                                                                                  │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "description": "Custom version string to use",                                                                  │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "version_string",                                                                                       │
│             │         "type": "string"                                                                                                │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "default_value": "0ms",                                                                                         │
│             │         "description": "Connection idle timeout",                                                                       │
│             │         "mandatory": false,                                                                                             │
│             │         "modifiable": true,                                                                                             │
│             │         "name": "wait_timeout",                                                                                         │
│             │         "type": "duration",                                                                                             │
│             │         "unit": "ms"                                                                                                    │
│             │     }                                                                                                                   │
│             │ ]                                                                                                                       │
├─────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ Commands    │ [                                                                                                                       │
│             │     {                                                                                                                   │
│             │         "attributes": {                                                                                                 │
│             │             "arg_max": 1,                                                                                               │
│             │             "arg_min": 1,                                                                                               │
│             │             "description": "Clear schemarouter shard map cache",                                                        │
│             │             "method": "POST",                                                                                           │
│             │             "parameters": [                                                                                             │
│             │                 {                                                                                                       │
│             │                     "description": "The schemarouter service",                                                          │
│             │                     "required": true,                                                                                   │
│             │                     "type": "SERVICE"                                                                                   │
│             │                 }                                                                                                       │
│             │             ]                                                                                                           │
│             │         },                                                                                                              │
│             │         "id": "clear",                                                                                                  │
│             │         "links": {                                                                                                      │
│             │             "self": "http://127.0.0.1:8989/v1/modules/schemarouter/clear/"                                              │
│             │         },                                                                                                              │
│             │         "type": "module_command"                                                                                        │
│             │     },                                                                                                                  │
│             │     {                                                                                                                   │
│             │         "attributes": {                                                                                                 │
│             │             "arg_max": 1,                                                                                               │
│             │             "arg_min": 1,                                                                                               │
│             │             "description": "Invalidate schemarouter shard map cache",                                                   │
│             │             "method": "POST",                                                                                           │
│             │             "parameters": [                                                                                             │
│             │                 {                                                                                                       │
│             │                     "description": "The schemarouter service",                                                          │
│             │                     "required": true,                                                                                   │
│             │                     "type": "SERVICE"                                                                                   │
│             │                 }                                                                                                       │
│             │             ]                                                                                                           │
│             │         },                                                                                                              │
│             │         "id": "invalidate",                                                                                             │
│             │         "links": {                                                                                                      │
│             │             "self": "http://127.0.0.1:8989/v1/modules/schemarouter/invalidate/"                                         │
│             │         },                                                                                                              │
│             │         "type": "module_command"                                                                                        │
│             │     }                                                                                                                   │
│             │ ]                                                                                                                       │
└─────────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

shell> maxctrl show commands schemarouter
┌────────────┬────────────┬──────────────────────────┐
│ Command    │ Parameters │ Descriptions             │
├────────────┼────────────┼──────────────────────────┤
│ clear      │ SERVICE    │ The schemarouter service │
├────────────┼────────────┼──────────────────────────┤
│ invalidate │ SERVICE    │ The schemarouter service │
└────────────┴────────────┴──────────────────────────┘

shell> maxctrl show dbusers Sharded-Service
┌───────────────────────┬────────────────┬───────────────────────┬───────┬───────┬────────┬───────┬──────┐
│ User                  │ Host           │ Plugin                │ TLS   │ Super │ Global │ Proxy │ Role │
├───────────────────────┼────────────────┼───────────────────────┼───────┼───────┼────────┼───────┼──────┤
│ PUBLIC                │                │                       │ false │ false │ false  │ false │      │
├───────────────────────┼────────────────┼───────────────────────┼───────┼───────┼────────┼───────┼──────┤
│ app                   │ 10.139.158.%   │ mysql_native_password │ false │ false │ false  │ false │      │
├───────────────────────┼────────────────┼───────────────────────┼───────┼───────┼────────┼───────┼──────┤
│ app_role              │                │                       │ false │ false │ false  │ false │      │
├───────────────────────┼────────────────┼───────────────────────┼───────┼───────┼────────┼───────┼──────┤
│ mariadb.sys           │ localhost      │ mysql_native_password │ false │ false │ false  │ false │      │
├───────────────────────┼────────────────┼───────────────────────┼───────┼───────┼────────┼───────┼──────┤
│ maxscale_admin        │ 10.139.158.210 │ mysql_native_password │ false │ false │ false  │ false │      │
├───────────────────────┼────────────────┼───────────────────────┼───────┼───────┼────────┼───────┼──────┤
│ maxscale_admin        │ 10.139.158.211 │ mysql_native_password │ false │ false │ false  │ false │      │
├───────────────────────┼────────────────┼───────────────────────┼───────┼───────┼────────┼───────┼──────┤
│ maxscale_admin_role   │                │                       │ false │ false │ false  │ false │      │
├───────────────────────┼────────────────┼───────────────────────┼───────┼───────┼────────┼───────┼──────┤
│ maxscale_monitor      │ 10.139.158.210 │ mysql_native_password │ false │ false │ false  │ false │      │
├───────────────────────┼────────────────┼───────────────────────┼───────┼───────┼────────┼───────┼──────┤
│ maxscale_monitor      │ 10.139.158.211 │ mysql_native_password │ false │ false │ false  │ false │      │
├───────────────────────┼────────────────┼───────────────────────┼───────┼───────┼────────┼───────┼──────┤
│ maxscale_monitor_role │                │                       │ false │ false │ false  │ false │      │
├───────────────────────┼────────────────┼───────────────────────┼───────┼───────┼────────┼───────┼──────┤
│ mysql                 │ localhost      │ mysql_native_password │ false │ true  │ true   │ false │      │
├───────────────────────┼────────────────┼───────────────────────┼───────┼───────┼────────┼───────┼──────┤
│ root                  │ localhost      │ mysql_native_password │ false │ true  │ true   │ false │      │
└───────────────────────┴────────────────┴───────────────────────┴───────┴───────┴────────┴───────┴──────┘

shell> maxctrl show commands mariadbmon
┌───────────────────────────┬─────────────────────────────┬───────────────────────────────────────────────────────────────────────────────┐
│ Command                   │ Parameters                  │ Descriptions                                                                  │
├───────────────────────────┼─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ switchover                │ MONITOR, [SERVER], [SERVER] │ Monitor name, New primary (optional), Current primary (optional)              │
├───────────────────────────┼─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ switchover-force          │ MONITOR, [SERVER], [SERVER] │ Monitor name, New primary (optional), Current primary (optional)              │
├───────────────────────────┼─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ async-switchover          │ MONITOR, [SERVER], [SERVER] │ Monitor name, New primary (optional), Current primary (optional)              │
├───────────────────────────┼─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ failover                  │ MONITOR                     │ Monitor name                                                                  │
├───────────────────────────┼─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ async-failover            │ MONITOR                     │ Monitor name                                                                  │
├───────────────────────────┼─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ rejoin                    │ MONITOR, SERVER             │ Monitor name, Joining server                                                  │
├───────────────────────────┼─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ async-rejoin              │ MONITOR, SERVER             │ Monitor name, Joining server                                                  │
├───────────────────────────┼─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ reset-replication         │ MONITOR, [SERVER]           │ Monitor name, Primary server (optional)                                       │
├───────────────────────────┼─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ async-reset-replication   │ MONITOR, [SERVER]           │ Monitor name, Primary server (optional)                                       │
├───────────────────────────┼─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ release-locks             │ MONITOR                     │ Monitor name                                                                  │
├───────────────────────────┼─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ async-release-locks       │ MONITOR                     │ Monitor name                                                                  │
├───────────────────────────┼─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ fetch-cmd-result          │ MONITOR                     │ Monitor name                                                                  │
├───────────────────────────┼─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ cancel-cmd                │ MONITOR                     │ Monitor name                                                                  │
├───────────────────────────┼─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ async-cs-add-node         │ MONITOR, STRING, STRING     │ Monitor name, Hostname/IP of node to add to ColumnStore cluster, Timeout      │
├───────────────────────────┼─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ async-cs-remove-node      │ MONITOR, STRING, STRING     │ Monitor name, Hostname/IP of node to remove from ColumnStore cluster, Timeout │
├───────────────────────────┼─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ cs-get-status             │ MONITOR                     │ Monitor name                                                                  │
├───────────────────────────┼─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ async-cs-get-status       │ MONITOR                     │ Monitor name                                                                  │
├───────────────────────────┼─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ async-cs-start-cluster    │ MONITOR, STRING             │ Monitor name, Timeout                                                         │
├───────────────────────────┼─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ async-cs-stop-cluster     │ MONITOR, STRING             │ Monitor name, Timeout                                                         │
├───────────────────────────┼─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ async-cs-set-readonly     │ MONITOR, STRING             │ Monitor name, Timeout                                                         │
├───────────────────────────┼─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ async-cs-set-readwrite    │ MONITOR, STRING             │ Monitor name, Timeout                                                         │
├───────────────────────────┼─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ async-rebuild-server      │ MONITOR, SERVER, [SERVER]   │ Monitor name, Target server, Source server (optional)                         │
├───────────────────────────┼─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ async-create-backup       │ MONITOR, SERVER, STRING     │ Monitor name, Source server, Backup name                                      │
├───────────────────────────┼─────────────────────────────┼───────────────────────────────────────────────────────────────────────────────┤
│ async-restore-from-backup │ MONITOR, SERVER, STRING     │ Monitor name, Target server, Backup name                                      │
└───────────────────────────┴─────────────────────────────┴───────────────────────────────────────────────────────────────────────────────┘

Literatur / Quellen