【问题标题】:Can not read response from server无法读取服务器的响应
【发布时间】:2012-03-30 00:54:48
【问题描述】:

我编写了一个 Java 程序,该程序连接到我服务器上的数据库,以查找记录、写入记录、更新和删除。出于某种原因,查找记录有效,但大多数情况下,当我尝试保存或写入记录时,它会显示一条错误消息:

com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

The last packet successfully received from the server was 9,787 milliseconds ago.       The last packet sent successfully to the server was 8,183 milliseconds ago.

Caused by: 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:2552)
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3002)
... 46 more

谁能解释为什么会这样? 通常,在我让软件运行大约半分钟后,尝试添加记录时,这会给我错误消息。似乎连接松动什么的。当我运行程序并快速写入新记录时,它可以工作

【问题讨论】:

  • 向我们展示代码中有意义的部分,这是我们猜测发生了什么的唯一方法。
  • 你应该小心管理丢失的连接stackoverflow.com/a/8997413/90909
  • 我的连接器类中有 con.close 方法。那可能是为什么?
  • 升级到 MySQL 5.6.28 为我解决了这个问题(从 5.5.40 开始)

标签: java mysql jdbc


【解决方案1】:

我遇到了同样的问题。我提到了许多帖子和 cmets,但对我有用的是更改 my.cnf 文件的一些参数。希望对你也有帮助....

my.cnf [mysqld]部分设置以下参数

interactive_timeout=180 # "No.of sec. a server waits for activity on interactive connection before closing it"

wait_timeout=180 # "No. of sec. a server waits for an activity on a connection before closing it"

max_connect_errors=9999 # "More than this number of interrupted connections from a host this host will be blocked from further connections"

skip-name-resolve # "Don't resolved host names. All host names are IP's"

【讨论】:

    【解决方案2】:

    有时这个问题是由于系统 RAM 的大小造成的。可能是您使用缓冲区通过 RAM 插入数据。为了摆脱这个问题。

    1. 在插入数据之前设置自动提交禁用。
    2. 插入一些适合您的系统 RAM(不是 整个)。
    3. 提交查询。
    4. 再次执行步骤 2 和 3,直到整个插入不再 完成。

    您可以通过以下代码来理解这一点。

    public static void main(string args[]) 
    {
      Connection con = null;
      Statement stm = null;
      int i;
      float ratio;
      ratio=1.0f;
      try
      {
        Class.forName("com.mysql.jdbc.Driver");
        // Connecting to the database
        con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/demo",
                                          "ashish", "impetus");
        File f = new File("filler"); // taking the random text data from the file
                                     // filler.txt and inserting that string
                                     // in filler field of the relations
        RandomAccessFile r = new RandomAccessFile(f,"r");
        Random randomGenerator = new Random();
        String strLine=new String();
        int r1,flag=0;
        stm = con.createStatement();
        con.setAutoCommit(false) ;
    
        int k=0;
        i=0;                
    
        long sum2=0;
        while(k%50000==0)
        {
          final long start = currentTimeMillis();
          final StringBuilder builder =
            new StringBuilder("INSERT INTO accounts 
                               (aid, bid,abalance,filler) VALUES ");
          while(i!=naccounts*ratio*scale )
            {
            int j=i+1;
            for(int l=0;l<40;l++)
            {
              strLine+=((char)r.read());
              r.skipBytes(0);
            }
            r1=randomGenerator.nextInt(1500);
            if(strLine.equals(""))
            {
              flag=1;
            }
            if(flag!=1)
            {   
              strLine=strLine.replaceAll("\\s","");
              strLine=strLine.replaceAll("\\t","");
            }                   
            flag=0;
            if (i%50000!=0) 
            {
              builder.append(",");
            }
            builder.append(format("(%s, %s, %s, '%s')", j, 
                           i/naccounts+1, 0, strLine));
            strLine="";
            r.seek(r1);
            i++;
            if(i%50000==0||i>=naccounts*ratio*scale)
            {   
              final String query = builder.toString();
              final PreparedStatement statement1 = con.prepareStatement(query);
              statement1.execute();
              con.commit();
              final long stop= currentTimeMillis();
              sum2=sum2+(stop-start);
              statement1.close();
            }
            if(i%50000==0||i>=naccounts*ratio*scale)
            {
              break;
            }
          }
          k=k+50000;
          if(k>naccounts*ratio*scale)
          {
            break;
          }
        }
        System.out.println(i+" rows inserted accounts table ");
        System.out.println("time taken = "+sum2+" milliseconds");
      }
      catch (SQLException e)
      {
        System.out.println("Connection Failed! Check output console");
        e.printStackTrace();
        return;
      }
      catch (Exception e) 
      {
        e.printStackTrace();
      }
    }
    

    【讨论】:

      【解决方案3】:

      您是否关注/阅读了本教程:

      Connectivity with MYSQL

      您的异常有一部分可能对您有用。

      我会引用一些关于您的特定异常的内容,请尝试一下:

      如果您收到 SQLException:连接被拒绝或连接超时 或 MySQL 特定的 CommunicationsException: Communications link 失败,则意味着数据库根本无法访问。这个可以 有以下一种或多种原因:

      JDBC URL 中的 IP 地址或主机名错误。 JDBC URL 中的主机名是 本地 DNS 服务器无法识别。端口号丢失或错误 JDBC URL。数据库服务器已关闭。数据库服务器不接受 TCP/IP 连接。数据库服务器已用完连接。里面的东西 Java 和 DB 之间的连接阻塞,例如防火墙或代理。

      要解决其中一个问题,请遵循以下建议:

      使用 ping 验证和测试它们。在 JDBC 中刷新 DNS 或使用 IP 地址 网址。根据 MySQL DB 的 my.cnf 进行验证。启动数据库。 验证 mysqld 是否在没有 --skip-networking 选项的情况下启动。 重新启动数据库并相应地修复您的代码以使其关闭 终于连接上了。禁用防火墙和/或配置 允许/转发端口的防火墙/代理。

      【讨论】:

      • 我关注了它,但我根据你的 url 做的一切都是正确的。我认为这是超时会话,这阻止了我对我的数据库做事。有什么办法可以防止会话超时?我已经阅读了一些关于 maxWait indefinate 的内容,但是找不到任何特定于如何声明它的内容,因此无论需要多长时间,系统都会等待直到收到响应。
      猜你喜欢
      • 2012-12-07
      • 1970-01-01
      • 2020-04-09
      • 2015-07-18
      • 2015-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-18
      相关资源
      最近更新 更多