用JDBC和MySQL解决"通信链路故障"

Ant*_*ony 187 java mysql jdbc

我正在尝试连接到本地MySQL服务器,但我一直收到错误.

这是代码.

public class Connect {

    public static void main(String[] args) {
        Connection conn = null;

        try {
            String userName = "myUsername";
            String password = "myPassword";

            String url = "jdbc:mysql://localhost:3306/myDatabaseName";
            Class.forName("com.mysql.jdbc.Driver").newInstance();
            conn = DriverManager.getConnection(url, userName, password);
            System.out.println("Database connection established");
        } catch (Exception e) {
            System.err.println("Cannot connect to database server");
            System.err.println(e.getMessage());
            e.printStackTrace();
        } finally {
            if (conn != null) {
                try {
                    conn.close();
                    System.out.println("Database Connection Terminated");
                } catch (Exception e) {}
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

和错误:

Cannot connect to database server
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.
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: 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.
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
        at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
        at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1116)
        at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:344)
        at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2333)
        at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2370)
        at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2154)
        at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:792)
        at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:47)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
        at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
        at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:381)
        at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:305)
        at java.sql.DriverManager.getConnection(DriverManager.java:582)
        at java.sql.DriverManager.getConnection(DriverManager.java:185)
        at Connect.main(Connect.java:16)
    Caused by: java.net.ConnectException: Connection refused
        at java.net.PlainSocketImpl.socketConnect(Native Method)
        at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:351)
        at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:213)
        at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:200)
        at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)
        at java.net.Socket.connect(Socket.java:529)
        at java.net.Socket.connect(Socket.java:478)
        at java.net.Socket.<init>(Socket.java:375)
        at java.net.Socket.<init>(Socket.java:218)
        at com.mysql.jdbc.StandardSocketFactory.connect(StandardSocketFactory.java:257)
        at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:294)
        ... 15 more
Run Code Online (Sandbox Code Playgroud)

我已经设置了类路径,确保my.cnf已经注释掉了skip网络选项.

java版本是1.2.0_26(64位)mysql 5.5.14 mysql连接器5.1.17

我确保用户可以访问我的数据库.

Soh*_*eil 370

我的两个程序中遇到了同样的问题.我的错误是这样的:

com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: 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.
Run Code Online (Sandbox Code Playgroud)

我花了几天时间来解决这个问题.我已经测试了许多在不同网站中提到过的方法,但是没有这些方法有效.最后我改变了我的代码,发现了问题所在.我会试着告诉你不同的方法并总结一下.

当我在寻找互联网找到这个错误的解决方案时,我发现有很多解决方案适用于至少一个人,但是其他人说这对他们不起作用! 为什么有很多这种错误的方法? 这似乎可以发生这种错误通常当在连接到服务器时出现问题.可能问题是由于错误的查询字符串或与数据库的连接太多.

所以我建议你逐一尝试所有的解决方案,不要放弃!

以下是我在互联网上找到的解决方案,对于每个解决方案,至少有人通过该解决方案解决了他的问题.

提示:对于需要更改MySQL设置的解决方案,可以参考以下文件:

  • Linux:/etc/mysql/my.cnf或/etc/my.cnf(取决于所使用的Linux发行版和MySQL包)

  • Windows:C:**ProgramData**\MySQL\MySQL Server 5.6\my.ini(注意它是ProgramData,而不是Program Files)

以下是解决方案:

  • 更改"bind-address"属性

取消注释"bind-address"属性或将其更改为以下IP之一:

绑定地址="127.0.0.1"

要么

绑定地址="0.0.0.0"

  • 评论"跳过网络"

如果MySQL配置文件中存在"跳过网络"行,请在该行的开头添加"#"符号进行注释.

  • 更改"wait_timeout"和"interactive_timeout"

将这些行添加到MySQL配置文件中:

wait_timeout = 数字

interactive_timeout = 数字

connect_timeout = 数字

  • 确保Java没有将'localhost'转换为[::: 1]而不是[127.0.0.1]

由于MySQL识别127.0.0.1(IPv4)但不识别::: 1(IPv6)

使用以下两种方法之一可以避免这种情况:

选项#1:在连接字符串中使用127.0.0.1而不是localhost,以避免将localhost转换为::: 1

选项#2:使用选项-Djava.net.preferIPv4Stack = true运行java以强制java使用IPv4而不是IPv6.在Linux上,这也可以通过运行(或将其放在/ etc/profile中来实现):

export _JAVA_OPTIONS="-Djava.net.preferIPv4Stack=true"
Run Code Online (Sandbox Code Playgroud)
  • 检查操作系统代理设置,防火墙和防病毒程序

确保防火墙或防病毒软件没有阻止MySQL服务.

暂时在linux上停止iptables.如果iptables配置错误,可能会允许将tcp数据包发送到mysql端口,但阻止tcp数据包返回同一连接.

# Redhat enterprise and CentOS
systemctl stop iptables.service
# Other linux distros
service iptables stop
Run Code Online (Sandbox Code Playgroud)

在Windows上停止防病毒软件.

  • 更改连接字符串

检查您的查询字符串.您的连接字符串应该是这样的事情:

dbName = "my_database";
dbUserName = "root";
dbPassword = "";
String connectionString = "jdbc:mysql://localhost/" + dbName + "?user=" + dbUserName + "&password=" + dbPassword + "&useUnicode=true&characterEncoding=UTF-8";
Run Code Online (Sandbox Code Playgroud)

确保字符串中没有空格.应该继续所有连接字符串,不带任何空格字符.

尝试将"localhost"替换为环回地址127.0.0.1.还尝试在连接字符串中添加端口号,例如:

String connectionString = "jdbc:mysql://localhost:3306/my_database?user=root&password=Pass&useUnicode=true&characterEncoding=UTF-8";
Run Code Online (Sandbox Code Playgroud)

通常MySQL的默认端口是3306.

不要忘记将用户名和密码更改为MySQL服务器的用户名和密码.

  • 更新JDK驱动程序库文件
  • 测试不同的JDK和JRE(如JDK 6和7)
  • 不要更改max_allowed_pa​​cket

" max_allowed_pa​​cket "是MySQL配置文件中的变量,表示最大数据包大小,而不是最大数据包数.所以它无助于解决这个错误.

  • 改变tomcat的安全性

将TOMCAT6_SECURITY = yes更改为TOMCAT6_SECURITY = no

  • 使用validationQuery属性

使用validationQuery ="select now()"来确保每个查询都有响应

  • autoReconnect的

将此代码添加到您的连接字符串:

&autoReconnect=true&failOverReadOnly=false&maxReconnects=10
Run Code Online (Sandbox Code Playgroud)

虽然这些解决方案都不适用于我,但我建议你尝试一下.因为有些人通过以下步骤解决了他们的问题.

但是什么解决了我的问题?

我的问题是我在数据库上有很多SELECT.每次我创建一个连接然后关闭它.虽然我每次关闭连接,但系统面临许多连接并给了我这个错误.我所做的是我将连接变量定义为整个类的公共(或私有)变量,并在构造函数中初始化它.然后我每次只使用那个连接.它解决了我的问题,也大大提高了我的速度.

结论

没有简单而独特的方法来解决这个问题.我建议你考虑一下自己的情况并选择上述解决方案.如果在程序开头出现此错误并且根本无法连接到数据库,则可能是连接字符串中存在问题.但是如果在几次成功交互到数据库后出现此错误,问题可能在于连接数量,您可能会考虑更改"wait_timeout"和其他MySQL设置,或者重写代码如何减少连接数.

  • 对我来说,它在 URL `jdbc:mysql://localhost:3306/cloudapp?useSSL=false&amp;allowPublicKeyRetrieval=true` 末尾添加 `useSSL=false&amp;allowPublicKeyRetrieval=true` (30认同)
  • 我只添加了wait_timeout,参考http://dev.mysql.com/doc/refman/5.1/en/server-system-variables.html#sysvar_wait_timeout (2认同)
  • @soheil *没有简单而独特的方法来解决这个问题。* 当然,但无论如何,你让我开心。我爱你。 (2认同)
  • @Soheil你可以添加"暂时禁用iptables",这是我的问题.iptables配置错误,允许将tcp数据包发送到mysql端口,但阻止tcp数据包返回同一连接. (2认同)

Pet*_*eph 12

如果你正在使用MAMP PRO,这个简单的解决方案,我真的希望在我开始搜索互联网几天之前我已经意识到这一点.真的很简单......

您只需从MAMP MySQL选项卡中单击"允许对MySQL进行网络访问".

真的,就是这样.

哦,您可能仍然需要将绑定地址更改为0.0.0.0或127.0.0.1,如上面的帖子中所述,但如果您是MAMP用户,单击该框可能会解决您的问题.


kai*_*ser 7

如果您在使用一组Docker 容器时遇到问题,请确保您不仅设置了EXPOSE端口3306,还从容器外部映射了端口-p 3306:3306。为了docker-compose.yml

\n\n
version: \'2\'\n\nservices:\n    mdb:\n        image: mariadb:10.1\n        ports:\n            - "3306:3306"\n        \xe2\x80\xa6\n
Run Code Online (Sandbox Code Playgroud)\n

  • 就像 @chris.currin 提到的,在从另一个 docker_container 访问时提供 `container_name` 很重要。示例 `"jdbc:mysql://mysql_container:3306/db_name?serverTimezone=UTC&amp;useSSL=false&amp;allowPublicKeyRetrieval=true"` (5认同)
  • 相关地,我尝试使用 localhost 或 127.0.0.1 或 0.0.0.0 或固定 IP 进行连接,但需要使用服务名称进行连接(此处: `jdbc:mysql://mdb:3306/...` ) (3认同)

Kev*_*nce 5

将设置设置bind-address为服务器的网络IP而不是localhost默认设置,并为我的用户设置权限.

my.cnf文件:

bind-address = 192.168.123.456
Run Code Online (Sandbox Code Playgroud)

MySql控制台:

GRANT ALL PRIVILEGES ON dbname.* to username@'%' IDENTIFIED BY 'password';
Run Code Online (Sandbox Code Playgroud)


Ren*_*ann 5

我刚刚遇到了同样的问题。发生这种情况是因为 MySQL 守护程序已绑定到计算机的 IP,需要该 IP 才能与有权连接 @your_machine 的用户建立连接。在这种情况下,用户应该有权连接 USER_NAME@MACHINE_NAME_OR_IP

我想远程访问我的机器,所以我在 my.cnf 中进行了更改

bind-address = MY_IP_ADDRESS
Run Code Online (Sandbox Code Playgroud)

bind-address = 0.0.0.0
Run Code Online (Sandbox Code Playgroud)

这将允许来自本地主机甚至外部(在我的情况下)的用户连接到该实例。如果将 MySQL 绑定到 0.0.0.0,则以下两个权限都将起作用:

USER_NAME@MACHINE_NAME_OR_IP

USER_NAME@localhost
Run Code Online (Sandbox Code Playgroud)


cin*_*oli 5

就我而言,

  1. 更改远程机器 mysql 配置/etc/mysql/my.cnf:更改 bind-address = 127.0.0.1#bind-address = 127.0.0.1

  2. 在远程计算机上,更改 mysql 用户权限 GRANT ALL PRIVILEGES ON *.* TO 'user'@'%' IDENTIFIED BY 'password';

  3. 重要提示:在远程计算机上重新启动 mysql:sudo /etc/init.d/mysql restart


Bar*_*run 5

就我而言(我是菜鸟),我正在测试与 MySQL 建立数据库连接的 Servlet,其中一个例外就是上面提到的那个。

它让我的头摇晃了几秒钟,但我开始意识到这是因为我没有在localhost.
启动服务器后,问题得到解决。

因此,请检查 MySQL 服务器是否正常运行