Re: LoadBalancingConnectionProxy and /* ping */ select 1
Posted by: Todd Farmer
Date: March 08, 2013 01:07PM

Hi Dom,

Wow, thanks for a well-considered and researched thread! I'll try to reply in kind.

You're absolutely right in seeing this as a bug - the ping should be executed against the master and all slaves. The comments you cite were originally authored for just load-balanced connections (those including the URL prefix "loadbalance:"). The ReplicationConnection (URLs including "replication:" prefix) was later modified to use the load-balancing connections under the hood, and ReplicationConnection.ping() calls ping() on the LoadBalancedConnection object:

public synchronized void ping() throws SQLException {
this.masterConnection.ping();
this.slavesConnection.ping();
}

The LoadBalancedMySQLConnection.ping() command is very straight-forward, only pinging the currently-active connection:

public void ping() throws SQLException {
getActiveMySQLConnection().ping();
}



This is because the code which pings all load-balanced servers is at a different level, though, found in LoadBalancingConnectionProxy.doPing(). That method is called from StatementImpl.doPingInstead(), which is called when a Statement or PreparedStatement find a SQL command starting with "/* ping */" (StatementImpl.PING_MARKER).

So, what happens here is:

1. A SQL command starting with "/* ping */" is issued on a ReplicationConnection.
2. It's intercepted and determined that there's no special handling, so it calls ReplicationConnection.ping().
3. That method calls ping() directly on the MySQLConnection for the master connection, and again on the LoadBalancedMySQLConnection.
4. The LoadBalancedMySQLConnection.ping() method expects that higher-level code in LoadBalancingConnectionProxy for load-balancing will handle delegating the ping() command to each underlying connection (of which it is one), so it only pings the current active connection.

I believe the simple solution to this would be to change the default behavior of LoadBalancedMySQLConnection.ping() such that it pings all underlying connections, and add an overloaded method to suppress this behavior when needed (probably required to prevent infinite loops from LoadBalancedConnectionProxy.doPing(), perhaps elsewhere):

public void ping(boolean allServers) throws SQLException {

if(!allServers) {
getActiveMySQLConnection().ping();
} else {
this.proxy.doPing();
}
}

public void ping() throws SQLException {

this.proxy.doPing();
}

I'll file a bug report and proposed patch to try for this early next week if I don't see anything already there.

Thanks again!

--
Todd Farmer
MySQL @ Oracle
http://www.oracle.com/mysql/



Edited 1 time(s). Last edit at 03/08/2013 01:09PM by Todd Farmer.

Options: ReplyQuote




Sorry, you can't reply to this topic. It has been closed.

Content reproduced on this site is the property of the respective copyright holders. It is not reviewed in advance by Oracle and does not necessarily represent the opinion of Oracle or any other party.