| Bug #75113 | Fail in failover of the connection in MySQL fabric | ||
|---|---|---|---|
| Submitted: | 5 Dec 2014 9:29 | Modified: | 3 Jun 2015 1:07 |
| Reporter: | Akiharu Yamada | Email Updates: | |
| Status: | Closed | Impact on me: | |
| Category: | Connector / J | Severity: | S2 (Serious) |
| Version: | 5.1.34 | OS: | Any |
| Assigned to: | Jess Balint | CPU Architecture: | Any |
| Tags: | fabric, failover, Mysql Fabric | ||
[5 Dec 2014 9:48]
Akiharu Yamada
The results when I succeeded in fail over are as follows. 1,SELECT,275 1,SELECT,0 1,SELECT,1 1,SELECT,1 1,SELECT,0 ----- SELECT ----- Error cause : null Error message: Server shutdown in progress Error status : 08S01 2,SELECT,0 2,SELECT,0 2,SELECT,1
[8 Dec 2014 1:56]
Akiharu Yamada
Result of diff command was incorrect. Correctly is as follows. also removes GROUP_MAP when close the handle of the connection.
$ diff -c ReplicationConnectionGroupManager.java.old ReplicationConnectionGroupManager.java.new
*** ReplicationConnectionGroupManager.java.old 2014-10-17 15:05:36.000000000 +0900
--- ReplicationConnectionGroupManager.java.new 2014-12-08 10:21:16.049604801 +0900
***************
*** 204,207 ****
--- 204,211 ----
}
+ public static ReplicationConnectionGroup removeGroup( String groupName )
+ {
+ return( GROUP_MAP.remove(groupName) );
+ }
}
$ diff -c ReplicationConnection.java.old ReplicationConnection.java.new
*** ReplicationConnection.java.old 2014-10-17 15:05:36.000000000 +0900
--- ReplicationConnection.java.new 2014-12-08 10:12:35.378693020 +0900
***************
*** 243,248 ****
--- 243,249 ----
if (this.connectionGroup != null) {
this.connectionGroup.handleCloseConnection(this);
+ ReplicationConnectionGroupManager.removeGroup( this.connectionGroup.getGroupName() );
}
}
***************
*** 2839,2844 ****
--- 2840,2846 ----
getCurrentConnection().abort(executor);
if (this.connectionGroup != null) {
this.connectionGroup.handleCloseConnection(this);
+ ReplicationConnectionGroupManager.removeGroup( this.connectionGroup.getGroupName() );
}
}
***************
*** 2878,2883 ****
--- 2880,2886 ----
getCurrentConnection().abortInternal();
if (this.connectionGroup != null) {
this.connectionGroup.handleCloseConnection(this);
+ ReplicationConnectionGroupManager.removeGroup( this.connectionGroup.getGroupName() );
}
}
[2 Apr 2015 15:31]
Jess Balint
Thank you for your bug report.
[2 Jun 2015 19:08]
Daniel So
Added the following entry to the Connector/J 5.1.36 changelog: "A failover did not occur for a MySQL Fabric connection during the failure of a master server. It was because the state change of the Fabric connection group was not handled properly, which hs been corrected by this fix."
[3 Jun 2015 1:07]
Akiharu Yamada
Thank you for bug fixes.

Description: When execute the following programs in MySQL Server constructed in MySQL Fabric and stop a master, fail in the failover of the connection. import java.sql.DriverManager; import java.sql.Connection; import java.sql.Statement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Properties; public class MySQLFabricTest { private static String hostname = "localhost"; private static String port = "32274"; private static String fabricServerGroup = "ha_group"; private static String fabricUsername = "admin"; private static String fabricPassword = "admin"; private static String database = "testdb"; private static String user = "root"; private static String password = "test"; public static boolean ExecuteQuery( Connection conn ) { boolean result = true; String server_id = null; String sqlState = null; long timeMillisStart = 0; long timeMillisEnd = 0; try { conn.setAutoCommit( true ); conn.setReadOnly( false ); ResultSet rs1 = conn.createStatement().executeQuery( "SHOW VARIABLES LIKE 'server\\_id'" ); rs1.next(); server_id = rs1.getString("Value"); rs1.close(); rs1 = null; timeMillisStart = System.currentTimeMillis(); ResultSet rs2 = conn.createStatement().executeQuery( "SELECT * from test" ); timeMillisEnd = System.currentTimeMillis(); rs2.close(); System.out.println( server_id + "," + "SELECT" + "," + String.valueOf(timeMillisEnd - timeMillisStart) ); Thread.sleep(1000); } catch( SQLException e ) { System.out.println( "----- SELECT -----" ); System.out.println( "Error cause : " + e.getCause() ); System.out.println( "Error message: " + e.getMessage() ); System.out.println( "Error status : " + e.getSQLState() ); result = false; } catch( InterruptedException e ) { } return( result ); } public static Connection db_connect() { Connection conn = null; Properties props = new Properties(); String baseUrl = "jdbc:mysql:fabric://" + hostname + ":" + Integer.valueOf(port) + "/"; props.put( "fabricServerGroup", fabricServerGroup ); props.put( "fabricUsername", fabricUsername ); props.put( "fabricPassword", fabricPassword ); props.put( "fabricReportErrors", "true" ); props.put( "user", user ); props.put( "password", password ); try { if( !com.mysql.jdbc.Util.isJdbc4() ) { Class.forName( "com.mysql.fabric.jdbc.FabricMySQLDriver" ); } conn = DriverManager.getConnection( baseUrl + database, props ); } catch( SQLException e ) { System.out.println( "----- CONNECT -----" ); System.out.println( "Error cause : " + e.getCause() ); System.out.println( "Error message: " + e.getMessage() ); System.out.println( "Error status : " + e.getSQLState() ); } catch( ClassNotFoundException e ) { } return( conn ); } public static void main(String args[]) throws Exception { Connection conn = db_connect(); while( true ) { if( !ExecuteQuery(conn) ) { conn.close(); conn = db_connect(); } } } } How to repeat: 1. Infomation in MySQL fabric $ mysqlfabric group lookup_servers ha_group Fabric UUID: 5ca1ab1e-a007-feed-f00d-cab3fe13249e Time-To-Live: 1 server_uuid address status mode weight ------------------------------------ -------------- --------- ---------- ------ 1b795d1b-7084-11e4-a5e3-005056827115 localhost:3306 PRIMARY READ_WRITE 1.0 ffe18ed4-7950-11e4-9f46-005056827115 localhost:3307 SECONDARY READ_ONLY 1.0 2. Execute a sample program $ java MySQLFabricTest 3. Stop a master of MySQL server $ mysqld_multi stop 1 $ mysqlfabric group lookup_servers ha_group Fabric UUID: 5ca1ab1e-a007-feed-f00d-cab3fe13249e Time-To-Live: 1 server_uuid address status mode weight ------------------------------------ -------------- ------- ---------- ------ 1b795d1b-7084-11e4-a5e3-005056827115 localhost:3306 FAULTY READ_WRITE 1.0 ffe18ed4-7950-11e4-9f46-005056827115 localhost:3307 PRIMARY READ_WRITE 1.0 4. Result of the sample program 1,SELECT,1 1,SELECT,1 1,SELECT,0 1,SELECT,1 ----- SELECT ----- Error cause : null Error message: Server shutdown in progress Error status : 08S01 ----- SELECT ----- Error cause : java.net.ConnectException: Connection refused Error message: Communications link failure The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server. Error status : 08S01 ----- SELECT ----- Error cause : java.net.ConnectException: Connection refused Error message: Communications link failure The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server. Error status : 08S01 : : Suggested fix: An old connection does not seem to be deleted. I succeeded in failover by changing the source code of the driver as follows. connectorj/src/com/mysql/jdbc/ReplicationConnectionGroupManager.java: --- 206,213 ---- } + public static ReplicationConnectionGroup removeGroup( String groupName ) + { + return( GROUP_MAP.remove(groupName) ); + } } connectorj/src/com/mysql/jdbc/ReplicationConnection.java: --- 275,281 ---- } if (this.connectionGroup != null) { + ReplicationConnectionGroupManager.removeGroup( this.connectionGroup.getGroupName() ); this.connectionGroup.handleCloseConnection(this); }