MySQL使用ReplicationConnection导致的连接失效分析与解决( 三 )


题外一问 :ping方法为什么使用“pingInternal” , 而不是常规的ping?原因:pingInternal预留了超时时间等控制参数 。

  • 解决方式
调整依赖版本服务中使用的mysql-jdbc版本为5.1.45 , druid版本为1.1.20 。经过对其他高版本依赖的了解 , 依然存在该问题 。
修改读写分离实现修改的工作量主要在于数据源配置和aop调整 , 但需要一定的整体回归验证成本 , 鉴于涉及该问题的服务重要性一般 , 暂不做大调整 。
拓展mysql-jdbc驱动基于原有ReplicationConnection的功能 , 拓展pingInternal调整为普通的ping , 集成原有Driver拓展新的Driver 。方案可行 , 但修改成本不算小 。
基于druid , 拓展MySQL连接检查为简单高效解决问题 , 选择拓展
MySqlValidConnectionChecker ,  并在 druid 数据源中加上对应配置即可 。拓展 如下:
public class MySqlReplicationCompatibleValidConnectionChecker extends MySqlValidConnectionChecker {private static final Log LOG = LogFactory.getLog(MySqlValidConnectionChecker.class);/****/private static final long serialVersionUID = 1L;@Overridepublic boolean isValidConnection(Connection conn, String validateQuery, int validationQueryTimeout) throws Exception {if (conn.isClosed()) {return false;}if (conn instanceof DruidPooledConnection) {conn = ((DruidPooledConnection) conn).getConnection();}if (conn instanceof ConnectionProxy) {conn = ((ConnectionProxy) conn).getRawObject();}if (conn instanceof ReplicationConnection) {try {((ReplicationConnection) conn).ping();LOG.info("validate connection success: connection=" + conn.toString());return true;} catch (SQLException e) {LOG.error("validate connection error: connection=" + conn.toString(), e);throw e;}}return super.isValidConnection(conn, validateQuery, validationQueryTimeout);}}
ReplicatoinConnection.ping()的实现逻辑中 , 会对所有master和slaves连接进行ping操作 , 最终每个ping操作都会调用到LoadBalancedConnectionProxy.doPing进行处理 , 而此处 , 可在数据库配置url中设置loadBalancePingTimeout属性设置超时时间 。




推荐阅读