Bug #39784 Make loadbalancing proxy exception handling global blacklist-aware
Submitted: 1 Oct 2008 16:40 Modified: 16 Oct 2008 14:24
Reporter: Todd Farmer (OCA) Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / J Severity:S3 (Non-critical)
Version:5.1.7 OS:Any
Assigned to: Todd Farmer CPU Architecture:Any

[1 Oct 2008 16: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 21:29] Todd Farmer
Fixed and pushed.
[16 Oct 2008 14: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.