访问远程服务器时MySQL连接出错

我在网络服务器上 托管了一个MySQL数据库 。 我已授予所有权限并允许我的IP从本地计算机远程连接到此数据库 。 它连接起来,我能够从数据库中检索数据到我的Java Swing应用程序。 但是,有时我收到此错误消息,并且我与托管数据库的连接失败。 错误如下所示:

Apr 7, 2012 12:49:20 AM scm.new_fas txtSearchKeyReleased SEVERE: null com.mysql.jdbc.CommunicationsException: Communications link failure due to underlying exception: ** BEGIN NESTED EXCEPTION ** java.io.EOFException MESSAGE: Can not read response from server. Expected to read 4 bytes, read 0 bytes before connection was unexpectedly lost. STACKTRACE: java.io.EOFException: Can not read response from server. Expected to read 4 bytes, read 0 bytes before connection was unexpectedly lost. at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:1997) at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2411) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2916) at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1631) at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1723) at com.mysql.jdbc.Connection.execSQL(Connection.java:3250) at com.mysql.jdbc.Connection.execSQL(Connection.java:3179) at com.mysql.jdbc.Statement.executeQuery(Statement.java:1207) at scm.DBControl.getResult(DBControl.java:49) at scm.new_fas.txtSearchKeyReleased(new_fas.java:1686) at scm.new_fas.access$2300(new_fas.java:28) at scm.new_fas$23.keyReleased(new_fas.java:1136) at java.awt.Component.processKeyEvent(Component.java:5999) at javax.swing.JComponent.processKeyEvent(JComponent.java:2794) at java.awt.Component.processEvent(Component.java:5815) at java.awt.Container.processEvent(Container.java:2058) at java.awt.Component.dispatchEventImpl(Component.java:4410) at java.awt.Container.dispatchEventImpl(Container.java:2116) at java.awt.Component.dispatchEvent(Component.java:4240) at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1848) at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(DefaultKeyboardFocusManager.java:693) at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(DefaultKeyboardFocusManager.java:958) at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:830) at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:657) at java.awt.Component.dispatchEventImpl(Component.java:4282) at java.awt.Container.dispatchEventImpl(Container.java:2116) at java.awt.Window.dispatchEventImpl(Window.java:2429) at java.awt.Component.dispatchEvent(Component.java:4240) at java.awt.EventQueue.dispatchEvent(EventQueue.java:599) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:173) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160) at java.awt.EventDispatchThread.run(EventDispatchThread.java:121) ** END NESTED EXCEPTION ** Last packet sent to the server was 2 ms ago. at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2622) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2916) at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1631) at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1723) at com.mysql.jdbc.Connection.execSQL(Connection.java:3250) at com.mysql.jdbc.Connection.execSQL(Connection.java:3179) at com.mysql.jdbc.Statement.executeQuery(Statement.java:1207) at scm.DBControl.getResult(DBControl.java:49) at scm.new_fas.txtSearchKeyReleased(new_fas.java:1686) at scm.new_fas.access$2300(new_fas.java:28) at scm.new_fas$23.keyReleased(new_fas.java:1136) at java.awt.Component.processKeyEvent(Component.java:5999) at javax.swing.JComponent.processKeyEvent(JComponent.java:2794) at java.awt.Component.processEvent(Component.java:5815) at java.awt.Container.processEvent(Container.java:2058) at java.awt.Component.dispatchEventImpl(Component.java:4410) at java.awt.Container.dispatchEventImpl(Container.java:2116) at java.awt.Component.dispatchEvent(Component.java:4240) at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1848) at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(DefaultKeyboardFocusManager.java:693) at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(DefaultKeyboardFocusManager.java:958) at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:830) at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:657) at java.awt.Component.dispatchEventImpl(Component.java:4282) at java.awt.Container.dispatchEventImpl(Container.java:2116) at java.awt.Window.dispatchEventImpl(Window.java:2429) at java.awt.Component.dispatchEvent(Component.java:4240) at java.awt.EventQueue.dispatchEvent(EventQueue.java:599) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:273) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:183) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:173) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:168) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:160) at java.awt.EventDispatchThread.run(EventDispatchThread.java:121) 

有人可以帮我解决这个问题。 我不明白什么是错的! 是服务器还是? 非常感谢 :)

这是我连接数据库的类:

 package scm; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; public class DBControl { private static DBControl con; private static String severIp = null; private static String severPort = null; private static String userName = null; private static String password = null; private static ResultSet rs = null; private static Connection cc = null; public DBControl() { } public static synchronized DBControl getInstance() { if (con == null) { con = new DBControl(); } return con; } public void setSeverIp(String Ip) { severIp = Ip; } public void setSeverPort(String Port) { severPort = Port; } public void SetUserName(String Name) { userName = Name; } public void setPassword(String passWord) { password = passWord; } public static ResultSet getResult(String url) throws Exception { Statement s = cc.createStatement(); rs = s.executeQuery(url); return rs; } public static Connection getConnection() throws Exception { // try { Class.forName("com.mysql.jdbc.Driver"); cc = (Connection) DriverManager.getConnection("jdbc:mysql://" + getSeverIp() + ":" + getSeverPort() + "/anuradha_rr", getUserName(), getPassword()); return cc; } public void setResult(String url) throws Exception { Class.forName("com.mysql.jdbc.Driver"); cc = (Connection) DriverManager.getConnection("jdbc:mysql://" + getSeverIp() + ":" + getSeverPort() + "/anuradha_rr", getUserName(), getPassword()); Statement s = (Statement) cc.createStatement(); s.executeUpdate(url); } public static String getSeverIp() { return severIp; } public static String getSeverPort() { return severPort; } public static String getUserName() { return userName; } public static String getPassword() { return password; } } 

确保您没有使用死jdbc连接。 根据您创建jdbc连接的方式,它们可能会空闲。 如果您反复使用相同的连接,请在尝试发出查询之前测试连接,如果已被mysql关闭,则获取新连接。

更新:

除了getResult()之外,您可以在任何地方创建新连接,这是堆栈跟踪标识错误的来源。 您可以像在其他任何地方一样创建新连接,也可以改进getConnection()的封装。 换句话说,更改getConnection()以返回存储在类中的静态Connection,条件是它不为null且仍然有效。 否则创建一个新连接并返回该连接。

这在MySQL中是一个相当普遍的问题,不幸的是,只有在生产中,当应用程序运行一段延长的时间时,通常只会在短的开发周期中发生。

MySQL在不通知其客户端的情况下关闭连接,并且当您尝试使用超时连接时,会出现不太明显的exception。 例如,您可以定期ping一些简单的SQL语句以避免超时。

最好使用连接池(以避免有太多用户同时访问数据库的问题),例如DBCP。 DBCP可以轻松添加到您的应用程序中,您只需将其设置为准JDBC驱动程序。 在那里你可以设置正确的方式。

我从我的一个项目中复制了这个DBCP配置:

  MaxActive=20, MaxWait=60000, TestWhileIdle=true, TimeBetweenEvictionRunsMillis=300000, MinEvictableIdleTimeMillis=300000, TestOnBorrow=true, ValidationQuery='SELECT 1' 

更新:作为一个非常简单的解决方案,您可以尝试在访问时捕获exception并在这种情况下打开新连接。