MySQL
Master/Slave Replication
JDBC URL
Database Management
SQL Replication

MySQL Master/Slave replication using jdbc url

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

If a Java application talks to a MySQL primary-replica setup, the JDBC URL alone does not magically solve routing, failover, or stale reads. Connector/J does support a replication-aware URL, but you still need to understand what the driver does with read-only versus read-write connections.

The key idea is simple: write traffic belongs on the primary, while read traffic can go to replicas when stale data is acceptable. The driver can help with that split, but only if the application uses it correctly.

What the Replication JDBC URL Does

Older examples often say "master/slave," but current MySQL documentation uses "source/replica" or "primary/replica." The URL pattern is still recognizable:

java
String url =
    "jdbc:mysql:replication://primary-db:3306,replica-a:3306,replica-b:3306/appdb";

That tells Connector/J it is connecting to a replication topology rather than a single server. Once the driver has that context, it can choose a host based on the connection mode.

The important point is that this is not query-by-query SQL parsing. The driver does not inspect every statement and decide whether it "looks like" a read or a write. Instead, the normal signal is whether the connection is marked read-only.

Read-Only Mode Controls Routing

With a replication connection, setReadOnly(true) is the application's way to say "this unit of work can go to a replica." If the connection is not read-only, the driver should use the primary.

Here is a minimal example with plain JDBC:

java
1import java.sql.Connection;
2import java.sql.DriverManager;
3import java.sql.ResultSet;
4import java.sql.Statement;
5
6public class Main {
7    public static void main(String[] args) throws Exception {
8        String url =
9            "jdbc:mysql:replication://primary-db:3306,replica-a:3306/appdb";
10
11        try (Connection connection =
12                 DriverManager.getConnection(url, "appuser", "secret")) {
13
14            connection.setReadOnly(true);
15
16            try (Statement stmt = connection.createStatement();
17                 ResultSet rs = stmt.executeQuery("SELECT NOW()")) {
18                while (rs.next()) {
19                    System.out.println(rs.getString(1));
20                }
21            }
22        }
23    }
24}

For write-oriented work:

java
1try (Connection connection =
2         DriverManager.getConnection(url, "appuser", "secret")) {
3
4    connection.setReadOnly(false);
5    connection.createStatement().executeUpdate(
6        "INSERT INTO audit_log(message) VALUES ('created row')"
7    );
8}

That is the core behavior to remember. If your application never marks connections read-only, the replication URL does not buy you much.

Why Many Production Systems Use Separate Pools

Even though the replication URL is valid, many teams still prefer two explicit data sources:

  • one pool pinned to the primary
  • one pool pinned to replicas

That design is less clever, but often more predictable. Connection pools reuse connections, and state such as read-only mode must be reset reliably between borrowers. If that reset is mishandled, a request can inherit the wrong intent from a previous one.

A split approach is easier to reason about:

java
String writeUrl = "jdbc:mysql://primary-db:3306/appdb";
String readUrl = "jdbc:mysql://replica-a:3306,replica-b:3306/appdb";

Then your service layer chooses the appropriate pool based on the operation. This also makes metrics, tracing, and operational debugging clearer because the architecture matches the database topology directly.

Replication Lag Still Exists

A replication-aware URL does not fix consistency. If a user writes a row on the primary and immediately performs a read, a replica may still be behind. That means the second request can legally return old data even though the setup is "working."

This is where application requirements matter:

  • if the request needs read-after-write consistency, use the primary
  • if stale reads are acceptable, replicas are fine
  • if failover matters, test the actual host-switch behavior in your environment

In other words, the JDBC URL is only a transport detail. Correctness still depends on your consistency rules.

A Practical Pattern

For many applications, the cleanest model is:

  1. send writes and strongly consistent reads to the primary
  2. send dashboard, search, or reporting reads to replicas
  3. keep those paths explicit in code

If you choose the replication URL route, verify how your framework and connection pool interact with setReadOnly. If you choose separate pools, make the read-versus-write choice explicit in the service layer. Both can work well; the second option is usually easier to debug.

Common Pitfalls

The most common mistake is assuming Connector/J will inspect SQL text and route individual statements automatically. In practice, the application usually has to communicate intent through connection state.

Another frequent problem is forgetting that pooled connections are reused. If a framework or pool does not restore read-only state correctly, one request can accidentally inherit another request's routing mode.

Teams also underestimate replication lag. A technically correct replication URL does not guarantee that a follow-up read from a replica will see the latest committed write.

Finally, do not treat failover as solved just because the URL lists multiple hosts. Test primary loss, replica unavailability, and reconnect behavior under your real driver and pool settings.

Summary

  • MySQL Connector/J supports a replication-aware JDBC URL for primary-replica topologies.
  • Read routing normally depends on setReadOnly(true), not on SQL parsing.
  • Separate read and write pools are often simpler and safer than one smart pool.
  • Replication lag still affects correctness, especially for read-after-write flows.
  • Test routing and failover behavior in your actual environment instead of assuming the driver will do exactly what you want.

Course illustration
Course illustration

All Rights Reserved.