Load Balancing MySQL servers using ProxySQL
What is ProxySql ?

ProxySql serves as an intermediary between a MySQL server and the applications that access its databases. ProxySQL can improve performance by distributing traffic among a pool of multiple database servers and also improve availability by automatically failing over to a standby if one or more of the database servers fail.
What is Mysql Replication?
MySQL database replication provides the facility to make replicas of databases. The ability to make exact copies of databases and keep them in real-time sync as changes are made at the “master” provides a number of advantages. In summary:
- Scaling out a database application
- Reducing database backup impact
- Facilitate reporting without affecting production load
- Failover/High Availability
Configuration of Mysql Replication
IN MASTER NODE
Uncomment or add the line in the file /etc/mysql/mysql.conf.d/mysqld.conf
server-id = 1
Then restart the mysql-server.
$ systemctl restart mysql
Creating a Replication User
$ mysql -u root -pmysql(master) > create user 'replica_user'@'replica_server_ip' IDENTIFIED WITH mysql_native_password BY 'password';mysql(master) > grant replication slave on *.* to 'replica_user'@'replica_server_ip';mysql(master) > flush privileges;
Retrieve Binary Log Co-ordinates from Source
When using MySQL’s binary log file position-based replication, you must provide the replica with a set of coordinates that detail the name of the source’s binary log file and a specific position within that file. The replica then uses these coordinates to determine the point in the log file from which it should begin copying database events and track which events it has already processed.
mysql(master) > flush tables with read lock;
mysql(master) > show master statusOutput:
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 899 | db | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
Migrate Data From Master To Slave
$ mysqldump -u root -p –all-databases > data.sql
$ scp data.sql root@<slave-ip-address>:/tmp/
$ unlock tables;
IN SLAVE NODE
Uncomment or add the line in the file /etc/mysql/mysql.conf.d/mysqld.conf
server-id = 2
Then restart the mysql-server.
$ systemctl restart mysql$ cd /tmp/
$ mysql -u root -p <data.sql$ mysql -u root -pmysql(slave) > select uuid();Output:
+--------------------------------------+
| uuid() |
+--------------------------------------+
| 45j52962b-l236-14tg-au71-0244ac123093 |
+--------------------------------------+
1 row in set (0.00 sec)Copy the content from the uuid and change it to the file location:
$ vi /var/lib/mysql/auto.cnf[auto]
server-uuid=45j52962b-l236-14tg-au71-0244ac123093
:wq$ systemctl restart mysqlmysql(slave) > change master to
> master_host='<master-host-ip>',
> master_user='replica_user',
> master_password='password',
> master_log_file='mysql-bin.000001',
> master_log_pos=899;mysql(slave) > START REPLICA;mysql(slave) > SHOW REPLICA STATUS \G;
Output
*************************** 1. row ***************************
Replica_IO_State: Waiting for master to send event
Source_Host: x.x.x.x
Source_User: replica_user
Source_Port: 3306
Connect_Retry: 60
Source_Log_File: mysql-bin.000001
Read_Source_Log_Pos: 1111
Relay_Log_File: mysql-relay-bin.000003
Relay_Log_Pos: 111
Relay_Source_Log_File: mysql-bin.000001
Installation of Proxy Sql
Assuming that the Operating Sytem being used is ubuntu:
$ wget https://github.com/sysown/proxysql/releases/download/v2.2.0/proxysql_2.2.0-ubuntu20_amd64.deb$ dpkg -i proxysql_2.2.0-ubuntu20_amd64.deb$ systemctl start proxysql
By default, ProxySql interface listens on port 6032. We can connect to proxysql using:
$ mysql -u admin -padmin -h 127.0.0.1 -P6032mysql(proxy) > show databases;
Define HostGroups
Proxysql uses a concept of hostgroups — a group of backend which serve the same purpose or handle similar type of traffic.When it comes to replication, at a minimum two types of backends come to mind — a master, which handles writes (and also reads, if needed) and slave (or slaves), which handles read-only traffic.
mysql(proxy) > INSERT INTO mysql_servers (hostgroup_id, hostname, port, max_replication_lag) VALUES (0, '172.17.0.2', 3306, 20);mysql(proxy) > INSERT INTO mysql_servers (hostgroup_id, hostname, port, max_replication_lag) VALUES (1, '172.17.0.3', 3306, 20);
What we did here is create 2 backend with ip 172.17.0.2 and 172.17.0.3. The first was assigned hostgroup ‘0’ acts as a master whereas the hostgroup with id ‘1’ acts as slave.
Define Application User
We create a user in proxysql, it authenticates against it and then makes a suitable connection to the backend server.
mysql(proxy) > INSERT INTO mysql_users (username, password, active, default_hostgroup, max_connections) VALUES ('proxyuser', 'proxypassword', 1, 0, 200);
Define Query Rule
ProxySQL uses query rules to route traffic. Those rules can distribute traffic across multiple hostgroups. In our case we define two rules, one is to read and another is to write.
WRITE
We are checking if the query is not by chance a select … for update. If it is, we will route it to hostgroup ‘0’ which is write.
mysql(proxy) > INSERT INTO mysql_query_rules (active, match_pattern, destination_hostgroup, cache_ttl) VALUES (1, '^SELECT .* FOR UPDATE', 0, NULL);
READ
Here we are checking if the query is a regular select. If so, it will be routed to the hostgroup ‘1’ which is the read hostgroup.
mysql(proxy) > INSERT INTO mysql_query_rules (active, match_pattern, destination_hostgroup, cache_ttl) VALUES (1, '^SELECT .*', 1, NULL);
Setup Monitoring Module And HealthCheck Timeout
Lets create a user for monitoring in the master mysql server instance.
mysql(master) > create user monuser@'ip' identified by 'monuser';
mysql(master) > grant replication client on *.* to monuser@'ip';
Now lets assign the correct username and password to the monitoring module.
mysql(proxy) > SET mysql-monitor_username='monuser';mysql(proxy) > SET mysql-monitor_password='monuser';mysql(proxy) > SET mysql-connect_timeout_server_max=20000;
Define read, write hostgroups and load the configs
The final step is to let ProxySql know which hostgroup or slave and master should belong to by adding the entries. ProxySql also doesn’t update runtime configuration when you make changes, so we make them persistance by saving them on the disk.
mysql(proxy) > INSERT INTO mysql_replication_hostgroups (writer_hostgroup, reader_hostgroup) VALUES (0, 1);mysql(proxy) > LOAD MYSQL USERS TO RUNTIME;
mysql(proxy) > SAVE MYSQL USERS TO DISK;mysql(proxy) > LOAD MYSQL QUERY RULES TO RUNTIME;
mysql(proxy) > SAVE MYSQL QUERY RULES TO DISK;mysql(proxy) > LOAD MYSQL VARIABLES TO RUNTIME;
mysql(proxy) > SAVE MYSQL VARIABLES TO DISK;mysql(proxy) > LOAD MYSQL SERVERS TO RUNTIME;
mysql(proxy) > SAVE MYSQL SERVERS TO DISK;
CONCLUSION:
In this way we have setup MySql Replication as well as ProxySql. The procedure outlined in this guide represents only one way of configuring the replication and proxy sql in MySql.