26.3.3.6. Using Master/Slave Replication with ReplicationConnection
Starting with Connector/J 3.1.7, we've made available a variant
of the driver that will automatically send queries to a
read/write master, or a failover or round-robin loadbalanced set
of slaves based on the state of
Connection.getReadOnly()
.
An application signals that it wants a transaction to be
read-only by calling
Connection.setReadOnly(true)
, this
“replication-aware” connection will use one of the
slave connections, which are load-balanced per-vm using a
round-robin scheme (a given connection is “sticky”
to a slave unless that slave is removed from service). If you
have a write transaction, or if you have a read that is
“time-sensitive” (remember, replication in MySQL is
asynchronous), set the connection to be not read-only, by
calling Connection.setReadOnly(false)
and
the driver will ensure that further calls are sent to the
“master” MySQL server. The driver takes care of
propagating the current state of autocommit, isolation level,
and catalog between all of the connections that it uses to
accomplish this load balancing functionality.
To enable this functionality, use the "
com.mysql.jdbc.ReplicationDriver
" class
when configuring your application server's connection pool or
when creating an instance of a JDBC driver for your standalone
application. Because it accepts the same URL format as the
standard MySQL JDBC driver,
ReplicationDriver
does not currently work
with java.sql.DriverManager
-based
connection creation unless it is the only MySQL JDBC driver
registered with the DriverManager
.
Here is a short, simple example of how ReplicationDriver might
be used in a standalone application.
import java.sql.Connection;
import java.sql.ResultSet;
import java.util.Properties;
import com.mysql.jdbc.ReplicationDriver;
public class ReplicationDriverDemo {
public static void main(String[] args) throws Exception {
ReplicationDriver driver = new ReplicationDriver();
Properties props = new Properties();
// We want this for failover on the slaves
props.put("autoReconnect", "true");
// We want to load balance between the slaves
props.put("roundRobinLoadBalance", "true");
props.put("user", "foo");
props.put("password", "bar");
//
// Looks like a normal MySQL JDBC url, with a comma-separated list
// of hosts, the first being the 'master', the rest being any number
// of slaves that the driver will load balance against
//
Connection conn =
driver.connect("jdbc:mysql://master,slave1,slave2,slave3/test",
props);
//
// Perform read/write work on the master
// by setting the read-only flag to "false"
//
conn.setReadOnly(false);
conn.setAutoCommit(false);
conn.createStatement().executeUpdate("UPDATE some_table ....");
conn.commit();
//
// Now, do a query from a slave, the driver automatically picks one
// from the list
//
conn.setReadOnly(true);
ResultSet rs = conn.createStatement().executeQuery("SELECT a,b,c FROM some_other_table");
.......
}
}