【问题标题】:Data source rejected establishment of connection, message from server: "Too many connections" [closed]数据源拒绝建立连接,来自服务器的消息:“连接太多”[关闭]
【发布时间】:2011-03-13 07:59:00
【问题描述】:

我正在尝试使用连接池库:DBPool 连接到我的数据库。这是我的源代码。

DBUtils.java

package DB;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import javax.sql.ConnectionPoolDataSource;
import snaq.db.ConnectionPool;
import com.mysql.jdbc.Driver;

/**
 * @author decorrea
 */
public class DBUtils {

    public static String jdbc_driver_name = "com.mysql.jdbc.Driver";    
    private static String server_name ;
    private static String database;
    private static String username;
    private static String password;

    public String getServer_name() {
        return server_name;
    }

    public void setServer_name(String serverName) {
        server_name = serverName;
    }

    public String getDatabase() {
        return database;
    }

    public void setDatabase(String database) {
        this.database = database;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    /*
     * Creates a MySQL DB connection from a pool
     */
    public Connection createConnection(ConnectionPool pool){

        Connection connection = null;
        try {
            // Load the JDBC driver
            Class driver_class = Class.forName(jdbc_driver_name);
            Driver driver = (Driver)driver_class.newInstance();
            DriverManager.registerDriver(driver);
            connection = pool.getConnection();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
        return connection;
    }

    /*
     * Creates a MySQL DB connection
     */
    public Connection createConnection(){
        Connection connection = null;
        try {
            // Load the JDBC driver
            Class driver_class = Class.forName(jdbc_driver_name);
            Driver driver = (Driver)driver_class.newInstance();
            DriverManager.registerDriver(driver);
            String url = "jdbc:mysql://" + server_name +  "/" + database;
            connection = DriverManager.getConnection(url);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
        return connection;
    }
}

TwitterAPI.java

/**
 * @author decorrea
 */
public class TwitterAPI {

    private static String server_name = "127.0.0.1";
    private static String twitter_databse = "twitter";
    private static String username = "root";
    private static String password = "password";

    public static Connection startDBConnection(String server_name, String database, String username, String password) {
        //Set DB parameters
        DBUtils mysql_obj = setDBParams(server_name, database, username, password);            
        String url = "jdbc:mysql://" + server_name +  "/" + database;
        ConnectionPool pool =  new ConnectionPool("local",1, 1, 1, 180000, url, username, password);
        Connection connection = mysql_obj.createConnection(pool);
        return connection;
    }

    public static DBUtils setDBParams(String server_name, String database, String username, String password){
        DBUtils mysql_obj = new DBUtils();
        mysql_obj.setServer_name(server_name);
        mysql_obj.setDatabase(database);
        mysql_obj.setUsername(username);
        mysql_obj.setPassword(password);
        return mysql_obj;
    }

    public static String getTweets(BigInteger id){
        Connection connection = startDBConnection(server_name,twitter_databse,username,password);       
        ResultSet resultSet = null;     
        String tweet = new String();
        try {           
            Statement statement = connection.createStatement();
            String query = SQL_queries.get_tweets_on_id  + id.toString();
            //Execute the query
            resultSet = statement.executeQuery(query);          
            while(resultSet.next()){
                tweet = resultSet.getString("content");
            }
            resultSet.close();
            statement.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        finally{
            try {
                connection.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return tweet;
    }
}

我是连接池业务的新手,并决定这样做只是因为我在没有它的情况下收到“通信链接故障”。

更新 1:补充一下,我还尝试了 Apache DBCP 并尝试了这个 example,但仍然收到相同的错误。

org.apache.commons.dbcp.SQLNestedException: Cannot create PoolableConnectionFactory (Data source rejected establishment of connection,  message from server: "Too many connections")
    at org.apache.commons.dbcp.BasicDataSource.createPoolableConnectionFactory(BasicDataSource.java:1549)
    at org.apache.commons.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1388)
    at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)
    at Twitter.TwitterAPI.startDBConnection(TwitterAPI.java:55)
    at Twitter.TwitterAPI.getTweets(TwitterAPI.java:84)
    at Twitter.TwitterAPI.main(TwitterAPI.java:235)
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Data source rejected establishment of connection,  message from server: "Too many connections"
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:45)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:528)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:409)
    at com.mysql.jdbc.Util.getInstance(Util.java:384)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1015)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:989)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:984)
    at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1105)
    at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2186)
    at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:787)
    at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:49)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:45)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:528)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:409)
    at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:357)
    at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:285)
    at org.apache.commons.dbcp.DriverConnectionFactory.createConnection(DriverConnectionFactory.java:38)
    at org.apache.commons.dbcp.PoolableConnectionFactory.makeObject(PoolableConnectionFactory.java:582)
    at org.apache.commons.dbcp.BasicDataSource.validateConnectionFactory(BasicDataSource.java:1556)
    at org.apache.commons.dbcp.BasicDataSource.createPoolableConnectionFactory(BasicDataSource.java:1545)
    ... 5 more
Exception in thread "main" java.lang.NullPointerException
    at Twitter.TwitterAPI.getTweets(TwitterAPI.java:108)
    at Twitter.TwitterAPI.main(TwitterAPI.java:235)

我还检查了 MySQL 中 my.ini 文件中的 max_connections 变量。这是它的价值:

MySQL 服务器将并发会话的最大数量 允许。这些连接之一将保留给具有 超级权限允许管理员登录,即使 已达到连接限制。 max_connections=100

MySQL 终端上的 show processlist 命令显示 101 个处于睡眠状态的进程。

任何形式的帮助/cmets 将不胜感激

更新 2 -- 解决方案:: 所以,我想出了解决方案。我没有在与数据库的 url 连接中提到端口名称。

String url = "jdbc:mysql://" + server_name +  "/" + database;

可能,因此它导致了许多泄漏连接。完成后,我尝试使用here 给出的示例。它现在不会抛出任何错误。感谢 BalusC,因为我只是因为他对更改 MySQL 上的端口号的评论才知道这一点。要补充的是,更改 MySQL 端口号的方法是NOT,通过更改 my.ini 文件,而是通过运行 MySQL 实例配置向导开始 -> 程序 -> MySQL Server 5.1 -> MySQL Server Instance Config Wizard。有趣的是,当没有指定端口号并且程序运行顺利时,代码没有抛出任何错误。可能 JDBC 默认连接到 3306。如果有人对此有任何特别的想法,请分享。

获取我的完整源代码see my answer below

【问题讨论】:

  • 编辑有什么特别的原因吗?
  • 您使用了&lt;pre&gt;&lt;code&gt;,这导致代码中出现嵌套滚动条。只需缩进 4 个空格或选择然后按消息编辑器工具栏中的010101 按钮或Ctrl+K 键即可很好地格式化代码。
  • BalusC 感谢您的提示。会记住的。

标签: java mysql jdbc


【解决方案1】:

org.apache.commons.dbcp.SQLNestedException:无法创建 PoolableConnectionFactory(数据源拒绝建立连接,来自服务器的消息:“连接太多”)

这表明 某事 正在泄漏连接。 IE。 something 不断获取(打开)连接,而从未关闭它们和/或返回连接池。重新启动数据库以便它可以硬关闭所有打开的连接应该可以暂时解决问题。修复 something 使其在使用后正确关闭连接应该可以永久解决问题。

虽然发布的 JDBC 代码没有遵循最佳习惯用法,但它看起来并不是连接泄漏的原因。可能数据库已经运行了数小时/数天,而您在早期的测试中获得了太多连接而没有关闭它们,以至于数据库用完了它们。

【讨论】:

  • BalusC,我确实关闭了 finally 块中 getTweets() 函数中的连接。这是我“建立”联系的唯一地方。还有什么可能泄漏?
  • 重启数据库并重新观察问题是否会再次出现。在您可能错过的编辑过程中,我带来了答案的最后一段。
  • BalusC,是的,我确实错过了。 1. 我已经多次重启了我的数据库,但没有任何效果 2. 代码不是最优的,但我对这个问题更好奇 3. 如前所述,我已经通过 MySQL 检查了连接,但没有其中似乎是个问题。
  • 嗯,看起来很像 其他东西 正在使用数据库。尝试更改数据库端口号(以便其他设备在不重新配置的情况下无法连接它)并在 Java 中重试。
  • BalusC,我尝试更改端口号并尝试使用 Java 没有成功。 :-(
【解决方案2】:

所以,我想出了解决方案。我没有在与数据库的 url 连接中提到端口名称。

String url = "jdbc:mysql://" + server_name +  "/" + database;

可能,因此它导致了许多泄漏连接。完成后,我尝试使用此处给出的示例。它现在不会抛出任何错误。感谢 BalusC,因为我只是因为他对更改 MySQL 上的端口号的评论才知道这一点。要添加,更改 MySQL 端口号的方法是 NOT 通过更改 my.ini 文件,而是通过在 Start -> Programs -> MySQL Server 5.1 -> MySQL Server Instance 下运行 MySQL 实例配置向导配置向导。有趣的是,当没有指定端口号并且程序运行顺利时,代码没有抛出任何错误。可能 JDBC 默认连接到 3306。如果有人对此有任何特别的想法,请分享。

为了方便大家,这里是源代码:

DBUtils.java

package DB;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
import com.mysql.jdbc.Driver;

/**
 * @author decorrea
 *
 */
public class DBUtils {

    public static String jdbc_driver_name = "com.mysql.jdbc.Driver";    

    private static String server_name ;
    private static String database;
    private static String username;
    private static String password;

    private static int maxActive = 20;
    private static int maxIdle = 2 ; 

    public String getServer_name() {
        return server_name;
    }

    public void setServer_name(String serverName) {
        server_name = serverName;
    }

    public String getDatabase() {
        return database;
    }

    public void setDatabase(String database) {
        this.database = database;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }


    public static DataSource getDataSource(String server_name, String database, String username, String password){

        BasicDataSource datasource = new BasicDataSource();
        datasource.setDriverClassName(jdbc_driver_name);
        String url = "jdbc:mysql://" + server_name +  "/" + database;
        System.out.println(url);
        datasource.setUsername(username);
        datasource.setPassword(password);
        datasource.setUrl(url);
        datasource.setMaxActive(maxActive);
        datasource.setMaxIdle(maxIdle);
        return datasource;
    }
}

TwitterAPI.java

public class TwitterAPI {

    private static String server_name = "localhost:7777";
    private static String twitter_databse = "twitter";
    private static String username = "root";
    private static String password = "password";
    public static String twitter_unique_usernames_file = "twitter_unique_usernames_file.txt";
    public static String language_model_file = "C:\\de\\JARS\\lingpipe-4.0.0\\demos\\models\\langid-leipzig.classifier";
    public static DataSource dataSource = DBUtils.getDataSource(server_name, twitter_databse, username, password);

    public static Connection startDBConnection(String server_name, String database, String username, String password) {
        //Set DB parameters
        //DBUtils mysql_obj = setDBParams(server_name, database, username, password);               

        Connection connection = null;
        //connection = mysql_obj.createConnection();
        try {
            connection = dataSource.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }

    public static DBUtils setDBParams(String server_name, String database, String username, String password){

        DBUtils mysql_obj = new DBUtils();
        mysql_obj.setServer_name(server_name);
        mysql_obj.setDatabase(database);
        mysql_obj.setUsername(username);
        mysql_obj.setPassword(password);
        return mysql_obj;
    }

    public static String getTweets(BigInteger id){

        Connection connection = startDBConnection(server_name,twitter_databse,username,password);       
        ResultSet resultSet = null;     
        String tweet = new String();
        try {           
            Statement statement = connection.createStatement();
            String query = SQL_queries.get_tweets_on_id  + id.toString();

            //Execute the query
            resultSet = statement.executeQuery(query);          

            while(resultSet.next()){
                tweet = resultSet.getString("content");
            }
            resultSet.close();
            statement.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        finally{
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return tweet;
    }

希望这会有所帮助。

【讨论】:

  • 有趣,我没想到省略端口号会导致这种行为......不使用连接池时也会发生这种情况吗?
  • BalusC,带有端口号 + 连接池:没问题。没有端口号+连接池:无法连接。没有端口号 + 没有连接池:可以运行有限的时间,但很快就会超过 max_number_of_connections。有端口号+无连接池:还没试过。
  • 对于仍然想知道此端口设置在哪里的人,请检查TwitterAPI 中的server_name 字段
猜你喜欢
  • 2012-08-18
  • 2011-08-12
  • 2015-04-03
  • 2014-05-01
  • 2016-10-28
  • 1970-01-01
  • 2010-10-30
  • 1970-01-01
相关资源
最近更新 更多