ServiceFramework icon indicating copy to clipboard operation
ServiceFramework copied to clipboard

数据库连接池问题

Open zhouzhenhao opened this issue 12 years ago • 12 comments

发现用MysqlClient 里面的方法都是数据库直连的方式 ,我要直接用sql执行,想用数据库连接池 有没有更好的方法 @allwefantasy

zhouzhenhao avatar Nov 21 '12 08:11 zhouzhenhao

不用担心。直接使用MysqlClient 使用的也是数据库连接池。

allwefantasy avatar Nov 21 '12 09:11 allwefantasy

client.defaultMysqlService().execute貌似我从这个方法的源码看到是直接关闭jdbc的Connection

public void execute(String sql, Object... params) {
        Connection conn = null;
        PreparedStatement preparedStatement = null;
        try {
            conn = getConnection();
            preparedStatement = conn.prepareStatement(sql);
            setParams(preparedStatement, params);
            preparedStatement.execute();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (preparedStatement != null) preparedStatement.close();
                if (conn != null) conn.close();
            } catch (SQLException e) {
                //ignore
            }

        }

    }

zhouzhenhao avatar Nov 21 '12 09:11 zhouzhenhao

可以看到,getConnection() 是通过dataSource获取connection的。 具体的方法为:

 private Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }

而dataSource 则是通过一个 DataSourceManager 类进行管理的。 如果感兴趣的话可以查看下该类的源码,代码比较简单。 通过DataSourceManager ,理论上可以配置多个数据源,不过这是后话了。

PS:另外你提到'直接关闭jdbc的Connection' 这个问题,实际返回的connection只是实现了java.sql.connection接口而已,并不是原来的com.mysql那个包下的。

allwefantasy avatar Nov 21 '12 11:11 allwefantasy

@allwefantasy 因为代码中用了 ServiceFramwork.injector.getInstance(MysqlClient.class); 来生成MysqlClient,发现每次生成一个MysqlClient造成了连接数一直在增加 ,是否有别的方法可以获得MysqlClient,而不会增加数据库连接的。
主要是在代码里面全部要用纯sql

zhouzhenhao avatar Nov 26 '12 08:11 zhouzhenhao

你是怎么发现数据库连接池一直在增加的?

public class PersistServiceModule extends AbstractModule {
    private Settings settings;

    public PersistServiceModule(Settings settings) {
        this.settings = settings;
    }

    @Override
    protected void configure() {
        bind(DataSourceManager.class).asEagerSingleton();
        bind(MysqlClient.class).in(Singleton.class);
        bind(MongoMongo.class).in(Singleton.class);

    }
}

这里是绑定的代码。MysqlClient是单例的。你之所以发现mysql数据库连接比较多,是因为程序关闭时没有通知 mysql 断开这些连接。

最合理的的方案是当关闭应用的时候同时关闭数据库连接池。 但是通常我们调试的时候也是比较野蛮的关闭。

现实生产环境你不会像开发那样经常关闭或者开启应用。所以不用担心数据库连接会满掉。

allwefantasy avatar Nov 26 '12 09:11 allwefantasy

@allwefantasy 不是单例的,我打印过MysqlClient的类信息 ,每次生成的MysqlClient是不一样的

zhouzhenhao avatar Nov 26 '12 09:11 zhouzhenhao

好的 那我测试一下。

allwefantasy avatar Nov 26 '12 09:11 allwefantasy

谢谢

zhouzhenhao avatar Nov 26 '12 09:11 zhouzhenhao

还有个要说下 你的数据库连接数不管在配置文件中怎么改 都是只有5个不变的 貌似代码里面写死了

zhouzhenhao avatar Nov 26 '12 09:11 zhouzhenhao

你能直接使用

MysqlClient client = Model.nativeSqlClient();

这种方式获取MysqlClient吗?

直接通过ServiceFramwork.injector.getInstance(MysqlClient.class); 已经被弃用。

然后你看看通过 MysqlClient client = Model.nativeSqlClient(); 多次获取是不是还是不一样?

allwefantasy avatar Nov 26 '12 09:11 allwefantasy

  ComboPooledDataSource dataSource = new ComboPooledDataSource();
            dataSource.setUser(mysqlSetting.get("username"));
            dataSource.setPassword(mysqlSetting.get("password"));
            dataSource.setJdbcUrl(url);
            dataSource.setDriverClass("com.mysql.jdbc.Driver");
            dataSource.setInitialPoolSize(5);
            dataSource.setMinPoolSize(5);
            dataSource.setMaxPoolSize(10);
            dataSource.setMaxStatements(50);
            dataSource.setMaxIdleTime(60);

这段配置你只要简单的改成:

     ComboPooledDataSource dataSource = new ComboPooledDataSource();
            dataSource.setUser(mysqlSetting.get("username"));
            dataSource.setPassword(mysqlSetting.get("password"));
            dataSource.setJdbcUrl(url);
            dataSource.setDriverClass("com.mysql.jdbc.Driver");
            dataSource.setInitialPoolSize(mysqlSetting.getAsInt("pool_size",5));
            dataSource.setMinPoolSize(mysqlSetting.getAsInt("min_pool_size",5));
            dataSource.setMaxPoolSize(mysqlSetting.getAsInt("max_pool_size",10));
            dataSource.setMaxStatements(50);
            dataSource.setMaxIdleTime(60);

然后修改配置文件,比如:

development:
    datasources:
        mysql:
           host: 127.0.0.1
           port: 3306
           database: wow
           username: root
           password: csdn.net
           disable: false
           pool_size:10

上面就将pool_size设置成了10.

修改的文件:

net.csdn.modules.persist.mysql.DataSourceManager

你如果急可以先自己改改。晚点我提交到主版本分支上。

allwefantasy avatar Nov 26 '12 09:11 allwefantasy

用MysqlClient client = Model.nativeSqlClient();获得以后是单例的了

zhouzhenhao avatar Nov 26 '12 10:11 zhouzhenhao