• MySQL知识库 :: jdbc
  • Using Replication-Aware Connections with MySQL and Connector/J

  • Summary

    A new feature in Connector/J 3.1 is a java.sql.Connection implementation that is aware of master/slave replication, and can be used to easily send write or write/immediate read operations to a master MySQL server, and load balance read-only operations across a pool of MySQL slave servers.

    Discussion

    A new feature available starting with Connector/J 3.1.5 is a ‘replication-aware‘ connection, which is basically a wrapper of two connections, one to a master, and another that is connected to one of a list of read-only slaves. To create a replication-aware connection, use the 'com.mysql.jdbc.ReplicationDriver' class instead of the normal 'com.mysql.jdbc.Driver' class when configuring your data sources.

    By signaling that your application wants a transaction to be read-only by calling Connection.setReadOnly(true), a ‘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 your application has a write transaction, or if it has a read transaction that is ‘time-sensitive‘ (remember, replication in MySQL is asynchronous), you just set the connection to be not read-only, by calling Connection.setReadOnly(false).

    The driver takes care of propagating the current state of autocommit, isolation level, and catalog between all of the connections that it uses.

    Here‘s a quick example of how you might use it:

    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();
    		props.put("autoReconnect", "true");
    		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);
    
    		// Do something on the master
    
    		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");
    	}
    }