In a real-world application, it's common to have multiple MySQL servers, like one for writes (primary) and several for reads (replicas). Managing this manually is complex and error-prone. Learn how Mafiree handles this end-to-end through our MySQL Database Administration services.
Without a load balancer, your app has no idea where to send queries — everything goes to the same server, even if others are available. This can lead to:
A load balancer solves this problem by sitting between your application and the database servers. It knows which server is healthy, which handles reads or writes, and routes queries accordingly — all without changes in your app code.
That’s exactly what MySQL Router does.
This blog explores how MySQL Router works under the hood, dives into advanced routing strategies, and shows you how to monitor and fine-tune your setup to keep your MySQL infrastructure fast, resilient, and always available.
In MySQL, load balancing is essential for distributing database traffic efficiently across multiple servers to improve performance, availability, and scalability. Here are the key load balancing options in MySQL:
MySQL Router is a lightweight, transparent proxy designed to route database traffic between your application and a MySQL backend cluster. It acts as an intelligent middleman that directs queries to the appropriate MySQL server based on the role of each server (e.g., primary or replica) and the type of query (read or write). It is a core component of any serious MySQL High Availability & Replication architecture. It's designed for:
Component | IP | Role | Port |
|---|---|---|---|
MySQL Primary | 127.0.0.1 | Read/Write | 3313 |
MySQL Replica 1 | 127.0.0.1 | Read-Only | 3306 |
MySQL Replica 2 | 127.0.0.1 | Read-Only | 3000 |
[logger]
level = INFO
[DEFAULT]
logging_folder=/var/log/mysqlrouter
[http_server]
port=8081
bind_address=127.0.0.1
[routing:primary_write]
bind_address = 0.0.0.0
bind_port = 6446
mode = read-write
destinations = 127.0.0.1:3313
routing_strategy = first-available
[routing:replica_read]
bind_address = 127.0.0.1
bind_port = 6447
mode = read-only
destinations = 127.0.0.1:3306, 127.0.0.1:3000
routing_strategy = round-robinMySQL Router supports several routing modes for different use cases:
MySQL Router supports several routing strategies under the routing_strategy configuration option. These define how MySQL Router chooses a backend server (MySQL instance) from a list of candidates when forwarding client connections.
MySQL 8.2, released in October 2023, introduced native transparent read/write splitting directly into MySQL client connectors — no proxy layer required.
Unlike MySQL Router where your application must explicitly connect to separate ports (6446 for writes, 6447 for reads), MySQL 8.2 handles the split automatically based on the query type. A single connection endpoint intelligently routes SELECT statements to replicas and write operations to the primary, all transparently.
How it works:
Enable it in your connection string:
mysqlx://root:password@127.0.0.1:33060?connect-attributes=_read_from_replicas=1
_read_from_replicas=1tells the connector to automatically routeSELECTqueries to replicas and writes to the primary.
For production environments running mixed MySQL versions or requiring advanced failover control, MySQL Router remains the recommended approach.
MySQL Router can be monitored using several methods: log files, Prometheus metrics, REST API, custom scripts, and integration with monitoring tools.
Among these, logging and the REST API are key—logs help track errors and connections, while the REST API provides real-time router status and detailed statistics for effective monitoring.
MySQL Router logging is essential for tracking its behavior, system events, and troubleshooting issues. You can configure the level of detail you want in the logs to suit your operational needs.
MySQL Router’s REST API offers a simple and effective way to monitor and manage routing within MySQL replica sets. It allows you to easily check the router’s status, view configured routes, and track important metrics to ensure smooth and reliable database traffic flow.
[http_server]
port=8081
bind_address=127.0.0.1
[rest_router]
require_realm=somerealm
[rest_routing]
require_realm=somerealm
[rest_metadata_cache]
require_realm=somerealm
[http_auth_realm:somerealm]
backend=somebackend
method=basic
name=Some Realm
[http_auth_backend:somebackend]
backend=file
filename=/etc/mysqlrouter/mysqlrouter.pwdEndpoint | Description | Plugin |
|---|---|---|
/router/status | Check Router status | rest_router |
/routes | List all routes | rest_routing |
/routes/{routeName}/blockedHosts | Get blocked IP addresses | rest_routing |
/routes/{routeName}/config | Get route configuration | rest_routing |
/routes/{routeName}/connections | Get active connections | rest_routing |
/routes/{routeName}/destinations | Get route destinations | rest_routing |
/routes/{routeName}/health | Check route health | rest_routing |
/routes/{routeName}/status | Get route status | rest_routing |
[sunil@centos7 ~]$ curl -u sunil:sunil http://127.0.0.1:8081/api/20190715/routes/primary_write/status | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 62 100 62 0 0 156k 0 --:--:-- --:--:-- --:--:-- 62000
{
"activeConnections": 1,
"totalConnections": 17,
"blockedHosts": 0
}[root@centos7 sunil]# curl -u sunil:sunil http://127.0.0.1:8081/api/20190715/routes/primary_write/config | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 235 100 235 0 0 506k 0 --:--:-- --:--:-- --:--:-- 229k
{
"bindAddress": "0.0.0.0",
"bindPort": 6446,
"clientConnectTimeoutInMs": 9000,
"destinationConnectTimeoutInMs": 5000,
"maxActiveConnections": 0,
"maxConnectErrors": 100,
"protocol": "classic",
"routingStrategy": "first-available",
"mode": "read-write"
}[root@centos7 sunil]# curl -u sunil:sunil http://127.0.0.1:8081/api/20190715/routes/primary_write/connections | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 339 100 339 0 0 436k 0 --:--:-- --:--:-- --:--:-- 331k
{
"items": [
{
"bytesFromServer": 11421,
"bytesToServer": 877,
"sourceAddress": "127.0.0.1:52532",
"destinationAddress": "127.0.0.1:3313",
"timeStarted": "2025-06-04T12:00:37.137264Z",
"timeConnectedToServer": "2025-06-04T12:00:37.147759Z",
"timeLastSentToServer": "2025-06-04T12:01:02.614366Z",
"timeLastReceivedFromServer": "2025-06-04T12:01:02.614797Z"
}
]
}
Zero-downtime MySQL routing is not about installing MySQL Router and hoping for the best. It is about understanding your traffic patterns, choosing the right routing strategy, and following a disciplined process of configuration and monitoring.
By splitting read and write traffic across dedicated ports and configuring proper failover destinations, you turn a fragile single-server bottleneck into a self-healing, load-balanced infrastructure.
The tools exist. The patterns are proven. What separates a smooth deployment from a 3 AM incident is planning, expertise, and real-time visibility. If you are scaling your MySQL environment and need professional guidance on MySQL High Availability & Replication or MySQL Database Administration, Mafiree is here to help.
Miru IT Park, Vallankumaranvillai,
Nagercoil, Tamilnadu - 629 002.
Unit 303, Vanguard Rise,
5th Main, Konena Agrahara,
Old Airport Road, Bangalore - 560 017.
Call: +91 6383016411
Email: sales@mafiree.com