Description:
Failover attempts between two read-write masters did not properly set this.currentConn.setReadOnly(false);
The shouldFallBack() is always returning (true) due to a counter not being reset.
How to repeat:
Setup 2 node circular replication for active-passive failover.
jdbc:mysql://host1,host2/reporting?failOverReadOnly=false&autoReconnectForPools=true&loadBalanceAutoCommitStatementThreshold=100&cacheCallableStmts=true&cachePrepStmts=true&connectTimeout=2000&socketTimeout=2000
Suggested fix:
Contributed fix:
--- FailoverConnectionProxy.java 2010-06-23 10:38:34.000000000 -0500
+++ FailoverConnectionProxy.java 2010-12-03 10:19:29.863892600 -0600
@@ -122,6 +122,14 @@
createPrimaryConnection();
return super.invoke(proxy, method, args);
+ } else if ("isClosed".equals(methodName)) {
+ InvocationHandler h=Proxy.getInvocationHandler(proxy);
+ if (h instanceof FailoverConnectionProxy) {
+ if (( ((FailoverConnectionProxy) h).failedOver) && shouldFallBack()) {
+ createPrimaryConnection();
+ return super.invoke(proxy, method, args);
+ }
+ }
}
return super.invoke(proxy, method, args);
@@ -179,7 +187,8 @@
}
super.pickNewConnection();
- this.currentConn.setReadOnly(true);
+ // this.currentConn.setReadOnly(true);
+ this.currentConn.setReadOnly(false);
this.failedOver = true;
}
@@ -193,9 +202,16 @@
private boolean shouldFallBack() {
long secondsSinceFailedOver = (System.currentTimeMillis() - this.masterFailTimeMillis) / 1000;
+ if (secondsSinceFailedOver >= this.secondsBeforeRetryMaster) {
+ this.masterFailTimeMillis=System.currentTimeMillis();
+ return true;
+ } else {
+ return false;
+ }
+
// Done this way so we can set a condition in the debugger
- boolean tryFallback = ((secondsSinceFailedOver >= this.secondsBeforeRetryMaster) || (this.queriesIssuedFailedOver >= this.queriesBeforeRetryMaster));
+ // boolean tryFallback = ((secondsSinceFailedOver >= this.secondsBeforeRetryMaster) || (this.queriesIssuedFailedOver >= this.queriesBeforeRetryMaster));
- return tryFallback;
+ // return tryFallback;
}
}