Configuring Backend MySQL Servers in ProxySQL
MySQL Servers are configured in the mysql_servers
and (optionally) mysql_replication_hostgroups
tables.
Note: Before reading the following section, please make sure you understand the multi-layer configuration system used by ProxySQL.
Specifically:
- changes in
mysql_servers
andmysql_replication_hostgroups
tables do not take effect without runningLOAD MYSQL SERVERS TO RUNTIME
- changes in
mysql_servers
andmysql_replication_hostgroups
tables are lost after a restart/crash if not saved to disk runningSAVE MYSQL SERVERS TO DISK
All changes in mysql_servers
and mysql_replication_hostgroups
tables do not take effect until LOAD MYSQL SERVERS TO RUNTIME
is executed, and are not persistent unless SAVE MYSQL SERVERS TO DISK
is executed.
Changes to mysql_servers
and mysql_replication_hostgroups
are to be considered as editing a config file without saving it or reloading the service.
IMPORTANT: all the examples below do not take effect until LOAD MYSQL SERVERS TO RUNTIME
is executed. SAVE MYSQL SERVERS TO DISK
is required to persist the configuration across ProxySQL restarts.
Copying mysql servers from memory to runtime
loads MySQL servers and replication hostgroups from the in-memory database to the runtime data structures
Admin> LOAD MYSQL SERVERS TO RUNTIME;
Other alias accepted:
LOAD MYSQL SERVERS TO RUN
LOAD MYSQL SERVERS FROM MEM
LOAD MYSQL SERVERS FROM MEMORY
Copying mysql servers from memory to disk
persists the MySQL servers and replication hostgroups from the in-memory database to the on-disk database
Admin> SAVE MYSQL SERVERS TO DISK;
Other alias accepted:
SAVE MYSQL SERVERS FROM MEM
SAVE MYSQL SERVERS FROM MEMORY
Copying mysql servers from runtime to memory
persists the MySQL servers and replication hostgroups from the runtime data structures to the in-memory database
Admin> SAVE MYSQL SERVERS TO MEMORY;
Other alias accepted:
SAVE MYSQL SERVERS TO MEM
SAVE MYSQL SERVERS FROM RUN
SAVE MYSQL SERVERS FROM RUNTIME
Copying mysql servers from disk to memory
loads MySQL servers and replication hostgroups from the on-disk database to the in-memory database
Admin> LOAD MYSQL SERVERS TO MEMORY;
Other alias accepted:
LOAD MYSQL SERVERS TO MEM
LOAD MYSQL SERVERS FROM DISK
Adding a new server
In order to add a new server, it must be defined inserting a new row in mysql_servers
table.
Note that the table has several columns with defaults.
The following adds a new backend with all default configuration:
Admin> SELECT * FROM mysql_servers;
Empty set (0.00 sec)
Admin> INSERT INTO mysql_servers (hostname) VALUES ('172.16.0.1');
Query OK, 1 row affected (0.00 sec)
Admin> SELECT * FROM mysql_servers\G
*************************** 1. row ***************************
hostgroup_id: 0
hostname: 172.16.0.1
port: 3306
gtid_port: 0
status: ONLINE
weight: 1
compression: 0
max_connections: 1000
max_replication_lag: 0
use_ssl: 0
max_latency_ms: 0
comment:
1 row in set (0.00 sec)
Adding new servers to a hostgroup
Admin> SELECT hostgroup_id,hostname FROM mysql_servers;
+--------------+------------+
| hostgroup_id | hostname |
+--------------+------------+
| 0 | 172.16.0.1 |
+--------------+------------+
1 row in set (0.00 sec)
Admin> INSERT INTO mysql_servers (hostgroup_id, hostname) VALUES (1, '172.16.0.2'), (1,'172.16.0.3');
Query OK, 2 rows affected (0.00 sec)
Admin> SELECT hostgroup_id,hostname FROM mysql_servers;
+--------------+------------+
| hostgroup_id | hostname |
+--------------+------------+
| 0 | 172.16.0.1 |
| 1 | 172.16.0.2 |
| 1 | 172.16.0.3 |
+--------------+------------+
3 rows in set (0.00 sec)
Limiting the number of connections to a backend
Admin> SELECT hostgroup_id,hostname,max_connections FROM mysql_servers;
+--------------+------------+-----------------+
| hostgroup_id | hostname | max_connections |
+--------------+------------+-----------------+
| 0 | 172.16.0.1 | 1000 |
| 1 | 172.16.0.2 | 1000 |
| 1 | 172.16.0.3 | 1000 |
+--------------+------------+-----------------+
3 rows in set (0.00 sec)
Admin> UPDATE mysql_servers SET max_connections=10 WHERE hostname='172.16.0.2';
Query OK, 1 row affected (0.00 sec)
Admin> SELECT hostgroup_id,hostname,max_connections FROM mysql_servers;
+--------------+------------+-----------------+
| hostgroup_id | hostname | max_connections |
+--------------+------------+-----------------+
| 0 | 172.16.0.1 | 1000 |
| 1 | 172.16.0.2 | 10 |
| 1 | 172.16.0.3 | 1000 |
+--------------+------------+-----------------+
3 rows in set (0.00 sec)
Prioritizing traffic by changing the weight of a backend
Weights are relevant only within a hostgroup
Admin> SELECT hostgroup_id,hostname,weight FROM mysql_servers;
+--------------+------------+--------+
| hostgroup_id | hostname | weight |
+--------------+------------+--------+
| 0 | 172.16.0.1 | 1 |
| 1 | 172.16.0.2 | 1 |
| 1 | 172.16.0.3 | 1 |
+--------------+------------+--------+
3 rows in set (0.00 sec)
Admin> UPDATE mysql_servers SET weight=1000 WHERE hostname NOT IN ('172.16.0.2', '172.16.0.1') AND hostgroup_id=1;
Query OK, 1 row affected (0.00 sec)
Admin> SELECT hostgroup_id,hostname,weight FROM mysql_servers;
+--------------+------------+--------+
| hostgroup_id | hostname | weight |
+--------------+------------+--------+
| 0 | 172.16.0.1 | 1 |
| 1 | 172.16.0.2 | 1 |
| 1 | 172.16.0.3 | 1000 |
+--------------+------------+--------+
3 rows in set (0.00 sec)
Using SSL connections for a specific backend
This example shows how to configure SSL for a backend. Although it does not show how to globally configure SSL. Check here for details on how to globally configure SSL.
Admin> SELECT hostgroup_id,hostname,use_ssl FROM mysql_servers;
+--------------+------------+---------+
| hostgroup_id | hostname | use_ssl |
+--------------+------------+---------+
| 0 | 172.16.0.1 | 1 |
| 1 | 172.16.0.2 | 0 |
| 1 | 172.16.0.3 | 0 |
+--------------+------------+---------+
3 rows in set (0.00 sec)
Automatically shunning slaves with replication lag
The Monitor module regularly checks replication lag if a server has max_replication_lag
set to a non-zero value.
Admin> SELECT hostgroup_id,hostname,max_replication_lag FROM mysql_servers;
+--------------+------------+---------------------+
| hostgroup_id | hostname | max_replication_lag |
+--------------+------------+---------------------+
| 0 | 172.16.0.1 | 0 |
| 1 | 172.16.0.2 | 0 |
| 1 | 172.16.0.3 | 0 |
+--------------+------------+---------------------+
3 rows in set (0.00 sec)
Admin> UPDATE mysql_servers SET max_replication_lag=30 WHERE hostname='172.16.0.3';
Query OK, 1 row affected (0.00 sec)
Admin> SELECT hostgroup_id,hostname,max_replication_lag FROM mysql_servers;
+--------------+------------+---------------------+
| hostgroup_id | hostname | max_replication_lag |
+--------------+------------+---------------------+
| 0 | 172.16.0.1 | 0 |
| 1 | 172.16.0.2 | 0 |
| 1 | 172.16.0.3 | 30 |
+--------------+------------+---------------------+
3 rows in set (0.00 sec)
With this configuration, server 172.16.0.3 will only be shunned in case replication delay exceeds 30 seconds behind master. In case max_replication_lag is set to zero (SET max_replication_lag=0), the Monitor module will not check replication lag at all i.e. with max_replication_lag set to 0 a host won’t be shunned if the replication lag exceeds the threshold, see mysql-monitor_slave_lag_when_null for more info.
Adding a server to two different hostgroups
The primary key on mysql_servers
table is defined as PRIMARY KEY (hostgroup_id, hostname, port)
. That means that the same server can be present in two different hostgroups, and there are multiple reasons why you may want to configure that.
For example, in a replication topology with one master and 2 slaves, you would like to send reads to the master if for any reason the slaves disappear (because they die, or because they lag too much).
Here’s an example:
Admin> SELECT hostgroup_id,hostname,weight,max_replication_lag FROM mysql_servers;
+--------------+------------+--------+---------------------+
| hostgroup_id | hostname | weight | max_replication_lag |
+--------------+------------+--------+---------------------+
| 0 | 172.16.0.1 | 1 | 0 |
| 1 | 172.16.0.2 | 1 | 0 |
| 1 | 172.16.0.3 | 1000 | 30 |
+--------------+------------+--------+---------------------+
3 rows in set (0.00 sec)
Admin> INSERT INTO mysql_servers(hostgroup_id,hostname) VALUES (1,'172.16.0.1');
Query OK, 1 row affected (0.00 sec)
Admin> SELECT hostgroup_id,hostname,weight,max_replication_lag FROM mysql_servers;
+--------------+------------+--------+---------------------+
| hostgroup_id | hostname | weight | max_replication_lag |
+--------------+------------+--------+---------------------+
| 0 | 172.16.0.1 | 1 | 0 |
| 1 | 172.16.0.2 | 1 | 0 |
| 1 | 172.16.0.3 | 1000 | 30 |
| 1 | 172.16.0.1 | 1 | 0 |
+--------------+------------+--------+---------------------+
4 rows in set (0.00 sec)
Admin> UPDATE mysql_servers SET max_replication_lag=30, weight=1000;
Query OK, 4 rows affected (0.00 sec)
Admin> UPDATE mysql_servers SET weight=1 WHERE hostname='172.16.0.1' AND hostgroup_id=1;
Query OK, 1 row affected (0.00 sec)
Admin> SELECT hostgroup_id,hostname,weight,max_replication_lag FROM mysql_servers;
+--------------+------------+--------+---------------------+
| hostgroup_id | hostname | weight | max_replication_lag |
+--------------+------------+--------+---------------------+
| 0 | 172.16.0.1 | 1000 | 30 |
| 1 | 172.16.0.2 | 1000 | 30 |
| 1 | 172.16.0.3 | 1000 | 30 |
| 1 | 172.16.0.1 | 1 | 30 |
+--------------+------------+--------+---------------------+
4 rows in set (0.00 sec)
In the example above, if we configure HG1 to serve read traffic, 99.95% of the traffic will be sent to 172.16.0.2 and 172.16.0.3, while 0.05% of the traffic will be normally sent to 172.16.0.1 . If 172.16.0.2 and 172.16.0.3 become unavailable, 172.16.0.1 will take all the read traffic.
Note: max_replication_lag
applies only to slaves. If a server doesn’t have replication enabled, Monitor won’t take any action.
Enable compression on a backend server
To enable compression it is enough to set mysql_servers
.compression
to a non-zero value. Note that compression will only be used for new connections initiated after the setting is loaded to runtime.
Admin> SELECT hostgroup_id,hostname,compression FROM mysql_servers;
+--------------+------------+-------------+
| hostgroup_id | hostname | compression |
+--------------+------------+-------------+
| 0 | 172.16.0.1 | 0 |
| 1 | 172.16.0.2 | 0 |
| 1 | 172.16.0.3 | 0 |
| 1 | 172.16.0.1 | 0 |
+--------------+------------+-------------+
4 rows in set (0.00 sec)
Admin> UPDATE mysql_servers SET compression=1 WHERE hostname='172.16.0.2' AND hostgroup_id=1;
Query OK, 1 row affected (0.00 sec)
Admin> SELECT hostgroup_id,hostname,compression FROM mysql_servers;
+--------------+------------+-------------+
| hostgroup_id | hostname | compression |
+--------------+------------+-------------+
| 0 | 172.16.0.1 | 0 |
| 1 | 172.16.0.2 | 1 |
| 1 | 172.16.0.3 | 0 |
| 1 | 172.16.0.1 | 0 |
+--------------+------------+-------------+
4 rows in set (0.00 sec)
Gracefully disabling a backend server
To gracefully disable a backend server it is required to change its status
to OFFLINE_SOFT
. Active transactions and connections will still be used, but no new traffic will be sent to the node.
Admin> SELECT hostgroup_id,hostname,status FROM mysql_servers;
+--------------+------------+--------+
| hostgroup_id | hostname | status |
+--------------+------------+--------+
| 0 | 172.16.0.1 | ONLINE |
| 1 | 172.16.0.2 | ONLINE |
| 1 | 172.16.0.3 | ONLINE |
| 1 | 172.16.0.1 | ONLINE |
+--------------+------------+--------+
4 rows in set (0.00 sec)
Admin> UPDATE mysql_servers SET status='OFFLINE_SOFT' WHERE hostname='172.16.0.2';
Query OK, 1 row affected (0.00 sec)
Admin> SELECT hostgroup_id,hostname,status FROM mysql_servers;
+--------------+------------+--------------+
| hostgroup_id | hostname | status |
+--------------+------------+--------------+
| 0 | 172.16.0.1 | ONLINE |
| 1 | 172.16.0.2 | OFFLINE_SOFT |
| 1 | 172.16.0.3 | ONLINE |
| 1 | 172.16.0.1 | ONLINE |
+--------------+------------+--------------+
4 rows in set (0.00 sec)
Immediately disabling a backend server
To immediately disable a backend server it is required to change its status
to OFFLINE_HARD
. All the current traffic will be immediately terminated, and no new traffic will be sent.
Admin> SELECT hostgroup_id,hostname,status FROM mysql_servers;
+--------------+------------+--------------+
| hostgroup_id | hostname | status |
+--------------+------------+--------------+
| 0 | 172.16.0.1 | ONLINE |
| 1 | 172.16.0.2 | OFFLINE_SOFT |
| 1 | 172.16.0.3 | ONLINE |
| 1 | 172.16.0.1 | ONLINE |
+--------------+------------+--------------+
4 rows in set (0.00 sec)
Admin> UPDATE mysql_servers SET status='OFFLINE_HARD' WHERE hostname='172.16.0.1' AND hostgroup_id=1;
Query OK, 1 row affected (0.00 sec)
Admin> SELECT hostgroup_id,hostname,status FROM mysql_servers;
+--------------+------------+--------------+
| hostgroup_id | hostname | status |
+--------------+------------+--------------+
| 0 | 172.16.0.1 | ONLINE |
| 1 | 172.16.0.2 | OFFLINE_SOFT |
| 1 | 172.16.0.3 | ONLINE |
| 1 | 172.16.0.1 | OFFLINE_HARD |
+--------------+------------+--------------+
4 rows in set (0.00 sec)
Re-enabling an offline / disabled backend server
To re-enable on offline backend it is enough to change its status back to ONLINE
:
Admin> SELECT hostgroup_id,hostname,status FROM mysql_servers;
+--------------+------------+--------------+
| hostgroup_id | hostname | status |
+--------------+------------+--------------+
| 0 | 172.16.0.1 | ONLINE |
| 1 | 172.16.0.2 | OFFLINE_SOFT |
| 1 | 172.16.0.3 | ONLINE |
| 1 | 172.16.0.1 | OFFLINE_HARD |
+--------------+------------+--------------+
4 rows in set (0.00 sec)
Admin> UPDATE mysql_servers SET status='ONLINE' WHERE status NOT IN ('ONLINE');
Query OK, 2 rows affected (0.00 sec)
Admin> SELECT hostgroup_id,hostname,status FROM mysql_servers;
+--------------+------------+--------+
| hostgroup_id | hostname | status |
+--------------+------------+--------+
| 0 | 172.16.0.1 | ONLINE |
| 1 | 172.16.0.2 | ONLINE |
| 1 | 172.16.0.3 | ONLINE |
| 1 | 172.16.0.1 | ONLINE |
+--------------+------------+--------+
4 rows in set (0.00 sec)
Removing a backend server
It is possible to completely remove a backend server by deleting it from mysql_servers
table.
Admin> SELECT hostgroup_id,hostname,status FROM mysql_servers;
+--------------+------------+--------+
| hostgroup_id | hostname | status |
+--------------+------------+--------+
| 0 | 172.16.0.1 | ONLINE |
| 1 | 172.16.0.2 | ONLINE |
| 1 | 172.16.0.3 | ONLINE |
| 1 | 172.16.0.1 | ONLINE |
+--------------+------------+--------+
4 rows in set (0.00 sec)
Admin> DELETE FROM mysql_servers WHERE hostgroup_id=1 AND hostname IN ('172.16.0.1','172.16.0.2');
Query OK, 2 rows affected (0.00 sec)
Admin> SELECT hostgroup_id,hostname,status FROM mysql_servers;
+--------------+------------+--------+
| hostgroup_id | hostname | status |
+--------------+------------+--------+
| 0 | 172.16.0.1 | ONLINE |
| 1 | 172.16.0.3 | ONLINE |
+--------------+------------+--------+
2 rows in set (0.00 sec)
Internally, deleting a backend or setting it OFFLINE_HARD
are handled in the same way. When LOAD MYSQL SERVERS TO RUNTIME
is executed, the Hostgroup_Manager will detect that a backend server was deleted and internally mark it as OFFLINE_HARD
.