使用 JDBC 和 MySQL 解决“通信链路故障” [重复]

Solving a "communications link failure" with JDBC and MySQL [duplicate]

提问人:Anthony 提问时间:7/29/2011 最后编辑:TinyAnthony 更新时间:11/8/2021 访问量:1265964

问:

我正在尝试连接到本地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) {}
            }
        }
    }
}

和错误:

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

我已经设置了类路径,确保my.cnf的跳过网络选项被注释掉了。

Java 版本为 1.2.0_26(64 位) MySQL的5.5.14 MySQL 连接器 5.1.17

我确保用户有权访问我的数据库。

java mysql jdbc

评论

7赞 Jim Garrison 7/29/2011
请注意底部的 CausedBy。SQL Server 从未接受该连接。如果 do(从命令行)会发生什么?mySQL服务器是否正在运行?telnet localhost 3306
0赞 Matt MacLean 7/29/2011
查看这篇文章。可能会有所帮助:stackoverflow.com/questions/15949/...
2赞 Anthony 7/29/2011
问题解决了,在my.cnf中添加了一个bind-address条目。
4赞 Fildor 11/2/2011
@Anthony 您应该将您的评论作为答案并接受它......
2赞 tinku 3/6/2013
我尝试在控制面板中转到 Windows 服务并启动 mysql 服务,然后它起作用了。试试这个解决方案

答:

496赞 Soheil 5/27/2012 #1

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

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.

我花了几天时间解决这个问题。我已经测试了许多在不同网站上提到的方法,但没有一个有效。最后,我更改了代码并找出了问题所在。我将尝试告诉您不同的方法并在此处进行总结

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

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

这是我在互联网上找到的解决方案,对于每个解决方案,至少有一个人的问题已经用该解决方案解决了。

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

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

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

以下是解决方案:

  • 更改属性:bind-address

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

     bind-address="127.0.0.1"
    

     bind-address="0.0.0.0"
    
  • 注释掉 “skip-networking”

    如果您的 MySQL 配置文件中有一行,请通过在该行的开头添加符号来使其注释。skip-networking#

  • 更改“wait_timeout”和“interactive_timeout”

    将以下行添加到MySQL配置文件中:

    [wait_timeout][1] = *number*
    
    interactive_timeout = *number*
    
    connect_timeout = *number*
    
  • 确保 Java 没有将“localhost”转换为 [:::1] 而不是 [127.0.0.1]

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

    这可以通过使用以下两种方法之一来避免:

    1. 在连接字符串中使用 instead of 以避免被转换为127.0.0.1localhostlocalhost:::1

    2. 运行 java 并带有强制 java to use 而不是 .在 Linux 上,这也可以通过运行(或将其放入 :-Djava.net.preferIPv4Stack=trueIPv4IPv6/etc/profile

       export _JAVA_OPTIONS="-Djava.net.preferIPv4Stack=true"
      
  • 检查操作系统代理设置、防火墙和防病毒程序

    确保防火墙或防病毒软件未阻止MySQL服务。

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

     # Redhat enterprise and CentOS
     systemctl stop iptables.service
     # Other linux distros
     service iptables stop
    

    停止 Windows 上的防病毒软件。

  • 更改连接字符串

    检查查询字符串。连接字符串应如下所示:Your connection string should be something like this:

    dbName = "my_database";
    dbUserName = "root";
    dbPassword = "";
    String connectionString = "jdbc:mysql://localhost/" + dbName + "?user=" + dbUserName + "&password=" + dbPassword + "&useUnicode=true&characterEncoding=UTF-8";
    

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

尝试将“localhost”替换为环回地址 127.0.0.1。 此外,请尝试将端口号添加到连接字符串中,例如:

String connectionString = "jdbc:mysql://localhost:3306/my_database?user=root&password=Pass&useUnicode=true&characterEncoding=UTF-8";

通常MySQL的默认端口是3306。

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

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

"max_allowed_packet“是MySQL配置文件中的一个变量,表示最大数据包大小,而不是最大数据包数。因此,解决此错误无济于事。

  • 更改 Tomcat 安全性

将 TOMCAT6_SECURITY=yes 更改为 TOMCAT6_SECURITY=no

  • 使用 validationQuery 属性

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

  • 自动重新连接

将此代码添加到连接字符串中:Add this code to your connection string:

&autoReconnect=true&failOverReadOnly=false&maxReconnects=10

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

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

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

#结论# 没有简单而独特的方法可以解决这个问题。我建议你考虑一下自己的情况,选择上面的解决方案。如果在程序开始时出现此错误,并且根本无法连接到数据库,则连接字符串可能有问题。但是,如果您在与数据库进行多次成功交互后出现此错误,则问题可能出在连接数量上,您可能会考虑更改“wait_timeout”和其他MySQL设置,或者重写代码以减少连接数量。

评论

3赞 Siddharth 4/5/2013
我只加了wait_timeout,指的是 dev.mysql.com/doc/refman/5.1/en/......
2赞 Basil Musa 2/8/2016
@Soheil 你能添加“暂时禁用iptables”吗,这是我的问题。iptables 配置错误,允许将 TCP 数据包发送到 MySQL 端口,但阻止 TCP 数据包在同一连接上返回。
1赞 thorinkor 5/17/2016
@Soheil感谢您的解决方案 - 对我来说,更改 MySQL 配置中的 wait_timeout 参数成功了!初始值仅设置为“300”!
1赞 Markus Barthlen 9/15/2016
使用正确的事务管理器后,事情变得非常快。谢谢。
30赞 Freeman 3/12/2019
对我来说,它是在URL的末尾添加的useSSL=false&allowPublicKeyRetrieval=truejdbc:mysql://localhost:3306/cloudapp?useSSL=false&allowPublicKeyRetrieval=true
1赞 Bozho 5/27/2012 #2

当MySQL没有足够的内存时,就会发生这种情况(就我而言)。重新启动可以修复它,但如果是这种情况,请考虑使用具有更多内存的 nachine,或者限制 jvms 占用的内存

评论

0赞 Kerem 3/18/2015
限制内存或只是获得更多内存似乎是一个临时解决方案,不是吗?
3赞 fuoco 9/20/2012 #3

就我而言,这是空闲超时,导致服务器上的连接断开。连接保持打开状态,但长时间未使用。然后客户端重新启动工作,而我相信重新连接也会工作。

一个不错的解决方案是让守护程序/服务不时 ping 连接。

1赞 tinku 3/6/2013 #4

转到控制面板中的Windows服务,然后启动MySQL服务。对我来说,它奏效了。当我做一个Java EE项目时,我遇到了这个错误“通信链接失败”。我重新启动了我的系统,然后它工作了。

之后,即使重新启动系统,我也再次出现相同的错误。然后我尝试打开MySQL命令行控制台并使用root登录,即使这样它也给了我一个错误。

最后,当我从 Windows 服务启动 MySQL 服务时,它起作用了。

1赞 user2180110 3/18/2013 #5

有一样的。 删除端口对我有帮助,所以我将其保留为 jdbc:mysql://localhost/

9赞 Kevin Lawrence 4/4/2013 #6

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

我的.cnf:

bind-address = 192.168.123.456

MySql 控制台:

GRANT ALL PRIVILEGES ON dbname.* to username@'%' IDENTIFIED BY 'password';

评论

1赞 Eric Kramer 1/22/2016
或者对所有接口使用 0.0.0.0...
0赞 alex 9/26/2016
答案对我有用,你能描述一下上面的MySQL指令是什么意思吗?@'%'
0赞 Daddy32 8/2/2017
bind-address = 0.0.0.0 对我有用。
0赞 Raul Luna 9/4/2013 #7

如果使用的是休眠,则此错误可能是由于将 Session 对象保持打开的时间超过wait_timeout

在这里为那些感兴趣的人记录了一个案例。

0赞 Mahmoud Zalt 9/13/2013 #8

我找到了解决方案

因为MySQL需要Localhost才能工作。

转到 /etc/network/interfaces 文件,并确保在那里设置了 localhost 配置:

auto lo
iface lo inet loopback

现在重新启动网络子系统和MySQL服务:

sudo /etc/init.d/networking 重新启动

sudo /etc/init.d/mysql 重启

立即试用

评论

0赞 Mahmoud Zalt 6/30/2014
不确定 Mac,这在 Linux Debian 上对我有用。
1赞 Meetai.com 7/1/2014
还行。这在更改MySQL端口并连接到该新端口后起作用。
0赞 Ankit Singhal 10/5/2013 #9

这主要是因为mysql客户端和远程mysql服务器之间的连接较弱。

就我而言,这是因为 VPN 连接不稳定。

3赞 devdanke 2/12/2014 #10

正如上面的详细答案所说,此错误可能是由多种原因引起的。

我也有这个问题。我的设置是 Mac OSX 10.8,使用 Ubuntu 12.04 的 Vagrant 托管 VirtualBox VM,以及 MySQL 5.5.34。

我在 Vagrant 配置文件中正确设置了端口转发。我可以从我的 Mac 和 VM 中远程登录到 MySQL 实例。所以我知道MySQL守护进程正在运行并且可以访问。但是当我尝试通过JDBC连接时,我收到了“通信链路失败”错误。

就我而言,通过编辑 /etc/mysql/my.cnf 文件解决了问题。具体来说,我注释掉了“#bind-address=127.0.0.1”行。

评论

0赞 Joe 3/28/2018
你在哪里改变了这一点?主机还是流浪者 MySql?
0赞 devdanke 4/11/2018
我在运行 MySQL 的来宾 VM 中进行了配置更改。我不希望MySQL直接在我的Mac上运行,所以我使用了VM。
0赞 gaRex 2/18/2014 #11

在phpstorm + vagrant autoReconnect驱动程序选项中有所帮助。

评论

0赞 Meetai.com 6/29/2014
得到:java.sql.SQLException:无法创建与数据库服务器的连接。尝试重新连接 3 次。放弃。
-4赞 Carlos 3/7/2014 #12

如果您使用的是本地模拟器,则必须使用 IP 地址 10.0.2.2 而不是 localhost 来访问本地 MySQL 服务器。

5赞 Renann 3/19/2014 #13

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

我想远程访问我的机器,所以我在 my.cnf 中从

bind-address = MY_IP_ADDRESS

bind-address = 0.0.0.0

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

USER_NAME@MACHINE_NAME_OR_IP

USER_NAME@localhost
5赞 cindyxiaoxiaoli 5/14/2014 #14

就我而言,

  1. 在以下位置更改远程计算机 mysql 配置: 更改为/etc/mysql/my.cnfbind-address = 127.0.0.1#bind-address = 127.0.0.1

  2. 在远程计算机上,使用GRANT ALL PRIVILEGES ON *.* TO 'user'@'%' IDENTIFIED BY 'password';

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

评论

0赞 Luis Crespo 5/7/2018
在 Ubuntu/Debian 中安装 MySQL 后,安装过程是安全的,默认情况下会阻止任何外部访问。为了从任何远程计算机访问MySQL,始终需要这些步骤。
2赞 Captain Dusty 5/18/2014 #15

在我的案例中,Soheil提供的解决方案是成功的。

澄清一下,我唯一需要做的更改是MySQL的服务器配置;

bind-address = **INSERT-IP-HERE**

我正在为我的应用程序使用外部MySQL服务器。它是使用 MySQL Server 5.5 的基本 Debian 7.5 安装 - 默认配置。

重要:

始终备份您可能修改的任何配置文件的原始文件。提升为超级用户时始终要小心。

文件

/etc/mysql/my.cnf

线

bind-address        = 192.168.0.103 #127.0.0.1

重新启动 MySQL Server 服务:

/usr/sbin/service mysql restart

如您所见,我只是提供了服务器的网络 IP 并注释掉了默认条目。请注意,简单地复制和粘贴我的解决方案不适合您,除非我们的主机奇迹般地共享相同的IP。

谢谢@Soheil

0赞 Saurab Dulal 7/4/2014 #16

我遇到了类似的问题,我的情况的解决方案是

  1. 从 127.0.0.1 更改 bind-address = 0.0.0.0
  2. 将 URL 的 localhost 更改为 localhost:3306

我觉得我们永远不应该放弃,我尝试了这篇文章和其他论坛的所有选项......很高兴它能@saurab

1赞 jpenaab 7/30/2014 #17

对我来说,解决方案是在mysql服务器的conf文件中将参数bind-address=“127.0.0.1”或bind-address=“x.x.x.x”更改为bind-address=“0.0.0.0”。 谢谢。

0赞 PHPFan 12/24/2014 #18

我也遇到过这个问题。

正如 Soheil 所建议的, 我转到路径 C:\windows\php.ini 中的 php.ini 文件,然后修改了此文件中的端口号。

它在线mysqli.default_port=..........

所以我在我的 java 应用程序中更改了它,因为它在 php.ini 文件中,现在它对我来说工作正常。

18赞 P.J. 12/30/2014 #19

如果您使用的是 MAMP PRO,那么简单的修复方法,我真的希望在我开始在互联网上搜索几天试图弄清楚这一点之前就已经意识到了这一点。真的这么简单......

您只需单击MAMP MySQL选项卡中的“允许对MySQL进行网络访问”。

真的,就是这样。

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

评论

0赞 Shantanu 7/30/2015
这为我节省了很多时间。当我知道这只是一个单线解决方案时,我能感觉到自己达到了沸点。
0赞 Strainy 1/11/2016
对我来说,这些端口与 MAMP 在起始页上所说的完全不同。进入 MAMP 首选项并检查端口选项卡以查看实际的 MySQL 端口是什么。
0赞 kimbaudi 1/11/2017
我的应用程序可以在 Windows 和 Ubuntu 上运行,但在具有 MAMP PRO 的 Mac 上运行。这也是我让我的应用程序在 Mac 上运行的方式。
2赞 thonnor 1/8/2015 #20

我知道这是一个旧线程,但我尝试了很多方法并使用以下方法解决了我的问题。

我正在 Windows 上开发一个跨平台应用程序,但要在 Linux 和 Windows 服务器上使用。

在两个系统上都安装了名为“jtm”的MySQL数据库。出于某种原因,在我的代码中,我的数据库名称为“JTM”。在 Windows 上它运行良好,实际上在几个 Windows 系统上它飞来飞去。

在Ubuntu上,我一次又一次地遇到上述错误。我在代码“jtm”中使用正确的大小写对其进行了测试,它很有效。

Linux 显然对区分大小写不那么宽容(这是正确的),而 Windows 则允许这样做。

我现在感觉有点傻,但检查一切。错误消息不是最好的,但如果您坚持不懈并把事情做好,它似乎是可以修复的。

评论

0赞 thonnor 12/5/2020
Linux 区分大小写
2赞 dulon 4/3/2015 #21

我刚刚重新启动了MySQL(按照这里的提示:https://stackoverflow.com/a/14238800)它解决了这个问题。

我在通过自制软件安装的 MacOS (10.10.2) 和 MySql (5.6.21) 上遇到了同样的问题。

令人困惑的是,我的一个应用程序连接到数据库很好,而另一个则没有。

在应用程序上尝试了许多抛出异常com.mysql.jdbc.CommunicationsException的事情后,正如这个问题的公认答案所建议的那样,无济于事,我很惊讶重新启动MySQL有效。

我的问题的原因可能是上述链接中的答案中建议的以下原因:

您在使用连接池吗?如果是,则尝试重新启动 服务器。连接池中可能很少有连接处于关闭状态。

0赞 Himanshu Narang 5/15/2015 #22

对于 Windows :- 转到开始菜单,编写“MySqlserver实例配置向导”,然后重新配置mysql服务器实例。 希望它能解决您的问题。

0赞 itpp13 6/13/2015 #23

在遇到相同的问题多年并且没有永久解决方案之后,这就是过去 3 周解决它的原因(这是无错误操作方面的记录)

设置全局wait_timeout=3600;
设置全局interactive_timeout=230400;

如果它适合您,请不要忘记将其永久化。

评论

0赞 ronit 5/24/2021
所以你把它增加到更长的时间。?这有帮助吗
5赞 Barun 9/19/2015 #24

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

这让我的头摆动了几秒钟,但我开始意识到这是因为我没有在 localhost 中启动我的 MySQL 服务器
启动服务器后,问题已修复。

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

6赞 kaiser 3/23/2016 #25

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

version: '2'

services:
    mdb:
        image: mariadb:10.1
        ports:
            - "3306:3306"
        …

评论

3赞 chris.currin 11/15/2017
与此相关的是,我尝试使用 localhost 或 127.0.0.1 或 0.0.0.0 或固定 ip 进行连接,但需要使用服务名称进行连接(此处:jdbc:mysql://mdb:3306/... )
5赞 prayagupa 6/26/2018
就像 @chris.currin 提到的,在从其他docker_container访问时提供这一点很重要。例container_name"jdbc:mysql://mysql_container:3306/db_name?serverTimezone=UTC&useSSL=false&allowPublicKeyRetrieval=true"
1赞 dheeraj kumar 1/19/2023
我在两个不同的容器中使用 tomcat 和 mysql 并出现相同的错误。使用 jdbc:mysql://mysql_container:3306/db_name 后。它解决了。