简体   繁体   English

MySql连接太多了

[英]MySql too many connections

I hate to bring up a question which is widely asked on the web, but I cant seem to solve it. 我讨厌提出一个在网络上被广泛询问的问题,但我似乎无法解决它。

I started a project a while back and after a month of testing, I hit a "Too many connections" error. 我在一段时间后开始了一个项目,经过一个月的测试后,我遇到了“Too many connections”错误。 I looked into it, and "Solved" it by increasing the max_connections. 我调查了它,并通过增加max_connections来“解决”它。 This then worked. 然后这工作。

Since then more and more people started to use it, and it hit again. 从那时起,越来越多的人开始使用它,它再次受到重创。 When I am the only user on the site, i type "show processlist" and it comes up with about 50 connections which are still open (saying "Sleep" in the command). 当我是网站上唯一的用户时,我输入“show processlist”,它会出现大约50个仍然打开的连接(在命令中说“Sleep”)。 Now, I dont know enough to speculate why these are open, but in my code I tripple checked and every connection I open, I close. 现在,我不知道为什么这些是开放的,但在我的代码中,我检查并检查每个连接,我关闭。

ie. 即。

public int getSiteIdFromName(String name, String company)throws DataAccessException,java.sql.SQLException{

Connection conn = this.getSession().connection();
Statement smt = conn.createStatement();
ResultSet rs=null;
String query="SELECT id FROM site WHERE name='"+name+"' and company_id='"+company+"'";

rs=smt.executeQuery(query);
rs.next();

int id=rs.getInt("id");

rs.close();
smt.close();
conn.close();
return id;
}

Every time I do something else on the site, another load of connections are opened and not closed. 每次我在网站上做其他事情时,都会打开另一个连接,但不会关闭。 Is there something wrong with my code? 我的代码有问题吗? and if not, what could be the problem? 如果没有,可能是什么问题?

With your approach, the connection will never be closed if any exception is been thrown before the conn.close() is called. 使用您的方法,如果调用conn.close() 之前抛出任何异常,则永远不会关闭连接。 You need to acquire it (and the statement and resultset) in a try block and close it in the finally block. 您需要在try块中获取它(以及语句和结果集)并在finally块中将其关闭。 Any code in finally will always be executed regardless of an exception is been thrown or not. 无论是否抛出异常,都将始终执行finally任何代码。 With this you can ensure that the expensive resources will be closed. 有了这个,您可以确保关闭昂贵的资源。

Here's a rewrite: 这是一个重写:

public int getSiteIdFromName(String name, String company) throws DataAccessException, java.sql.SQLException {
    Connection conn = null;
    Statement smt = null;
    ResultSet rs = null;
    int id = 0;
    try {
        conn = this.getSession().connection();
        smt = conn.createStatement();
        String query = "SELECT id FROM site WHERE name='" + name + "' and company_id='" + company + "'";
        rs = smt.executeQuery(query);
        rs.next();
        id = rs.getInt("id");
    } finally {
        if (rs != null) try { rs.close(); } catch (SQLException logOrIgnore) {}
        if (smt != null) try { smt.close(); } catch (SQLException logOrIgnore) {}
        if (conn != null) try { conn.close(); } catch (SQLException logOrIgnore) {}
    }
    return id;
}

That said, this code is sensitive to SQL injection attacks . 也就是说,此代码对SQL注入 攻击很敏感。 Use a PreparedStatement instead of Statement . 使用PreparedStatement而不是Statement

See also : 另见

One possible flow in which this code can leak connection is: 此代码可能泄漏连接的一个可能流程是:

  1. Stmt.executeQuery() results empty resultset Stmt.executeQuery()导致空结果集
  2. You do not check whether rs.next() returns true or false 您不检查rs.next()是返回true还是false
  3. rs.getInt("id") throws exception as there is not current row in resultset rs.getInt(“id”)抛出异常,因为resultset中没有当前行
  4. conn.close() is skipped 跳过conn.close()

Do the following: 请执行下列操作:

  1. Make rs.getInt() conditional on rs.next() 使rs.getInt()以rs.next()为条件
  2. Close the connection in finally block and do all the data access within try block 关闭finally块中的连接,并在try块中进行所有数据访问

Edit: 编辑:

Also it's a good idea to log all exceptions somewhere so that you have a good starting point in your troubleshooting. 此外,在某处记录所有异常也是一个好主意,这样您就可以在故障排除中找到一个很好的起点。

If the code throws a DataAccessException or java.sql.SQLException the connection will not be closed resulting in many open sleeping connections ;) Make a try-finally-Block which will close the connection. 如果代码抛出DataAccessException或java.sql.SQLException,则连接将不会关闭,导致许多打开的睡眠连接;)创建一个try-finally-Block,它将关闭连接。

Connection conn = this.getSession().connection();
try {
  // all code
} finally {
  rs.close();
  smt.close();
  conn.close();
}

It's a trivial example but a little more complex because you have to check wich of these objects are really created and used. 这是一个简单的例子,但有点复杂,因为你必须检查这些对象是否真正被创建和使用。

The temporary solution for this problem can be increasing the allowed maximum connections of the mysql.You can do this by the below mentioned either of the two ways. 这个问题的临时解决方案可以增加mysql允许的最大连接数。你可以通过下面提到的两种方式之一来做到这一点。

First: 第一:

Login into the mysql server and type the below given command. 登录到mysql服务器并输入以下给定的命令。

mysql> SET GLOBAL max_connections = 200;

This will increase the maximum connections.But this setting will change if the server is restarted. 这将增加最大连接数。但是,如果重新启动服务器,此设置将更改。

Second: 第二:

Edit the file /etc/mysql/my.cnf and increase the max_connection in this file. 编辑文件/etc/mysql/my.cnf并增加此文件中的max_connection。

[mysqld]
local-infile=0
datadir=/var/lib/mysql
user=mysql
symbolic-links=0

max_connections = 100

Save the changes and type the following to restart mysqld: 保存更改并键入以下内容以重新启动mysqld:

/etc/init.d/mysqld restart

But this problem , usually appears because of the open connections that are not properly close and are unavailable to use. 但是这个问题通常是由于未正确关闭且无法使用的打开连接而出现的。

Just try looking into all of the resources that are accessing your data base and check if all the connections are properly handled. 只需尝试查看访问数据库的所有资源,并检查是否正确处理了所有连接。

looking into the code it can be seen that you have not placed the code in the try and catch. 查看代码可以看出,您没有将代码放在try和catch中。

According to your code , if the exception occurs in fetching the data your connection will not be closed and hence it will be a waste of resource.Hence as the coding standard suggests use the try and catch with finally to handle the connections. 根据您的代码,如果在获取数据时发生异常,您的连接将不会被关闭,因此这将浪费资源。因为编码标准建议使用try和catch来最终处理连接。

try{
//your code 
}
catch(Exception e){

//handle the exceptions here
}

finally{
        try{
            channel.close();
        } catch(Exception e){
            log.error("Error is "+e.getMessage(),e);
            e.printStackTrace();
        }
        try {
            connection.close();
        } catch (IOException e) {
            log.error("Error is "+e.getMessage(),e);
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        catch(Exception e){
            log.error("Error is "+e.getMessage(),e);
            e.printStackTrace();
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM