Bug #39784 Make loadbalancing proxy exception handling global blacklist-aware
Submitted: 1 Oct 2008 18:40 Modified: 16 Oct 2008 16:24
Reporter: Todd Farmer
Status: Closed
Category:Connector/J Severity:S3 (Non-critical)
Version:5.1.7 OS:Any
Assigned to: Todd Farmer Target Version:5.1.8

[1 Oct 2008 18:40] Todd Farmer
Description:
When the LoadBalancingConnectionProxy handles a SQLException with SQL state starting with
"08", it calls invalidateCurrentConnection(), which in turn removes that Connection from
liveConnections and the connectionsToHostsMap, but it does not currently add the host to
the new global blacklist (if enabled).

There is also the possibility of a NPE when trying to update stats where
connectionsToHostsMap.get(this.currentConn) is called:

int hostIndex = ((Integer) this.hostsToListIndexMap
		.get(this.connectionsToHostsMap.get(this.currentConn)))
							.intValue();

This can happen if a client tries to issue a rollback after catching a SQLException
caused by a connection failure.

How to repeat:
  import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Date;

public class BasicConnectionLBTest {
	public static void main(String[] args) {
		try {
			Class.forName("com.mysql.jdbc.Driver");
			Connection conn = DriverManager
					.getConnection(
							"jdbc:mysql:loadbalance://localhost:3307,localhost:3306/test?retriesAllDown=30&loadBalanceBlacklistTimeout=500&connectTimeout=100",
							"root", null);
			conn.setAutoCommit(false);
			while ( true ) {

				// kill one of the mysqld instances sometime here.
				try {
				Statement stmt = conn.createStatement();
				ResultSet rs = stmt.execute("SELECT SLEEP(1)");
					
				conn.commit();
				} catch (SQLException e) {
					try{
						conn.rollback();
					} catch (Exception se) {
						se.printStackTrace();		
					}

				}

			}

		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
[15 Oct 2008 23:29] Todd Farmer
Fixed and pushed.
[16 Oct 2008 16:24] Tony Bedford
An entry was added to the 5.1.7 changelog:

When the LoadBalancingConnectionProxy handles a SQLException with SQL state starting with
“08”, it calls invalidateCurrentConnection, which in turn removes that Connection from
liveConnections and the connectionsToHostsMap, but it did not add the host to the new
global blacklist, if the global blacklist was enabled. 

There was also the possibility of a NullPointerException when trying to update stats,
where connectionsToHostsMap.get(this.currentConn) was called: 

int hostIndex = ((Integer)
this.hostsToListIndexMap.get(this.connectionsToHostsMap.get(this.currentConn))).intValue();

This could happen if a client tried to issue a rollback after catching a SQLException
caused by a connection failure.