1. 直接获取Connection问题

  1. 传统的JDBC数据库连接使用DriverManager来获取,每次向数据库建立连接的时候都要将Connection加载到内存中,在验证IP地址用户名和密码(0.05s~1s时间)。需要数据库连接的时候,就向数据库请求一个,频繁地进行数据库连接操作将占用很多的系统资源,容易造成服务器崩溃。
  2. 每一次数据库连接,使用完成后都得断开,如果程序出现异常而未能关闭,将导致数据库内存泄漏,最终将导致重启数据库。
  3. 传统获取连接的方式,不能控制创建的连接数量,如果连接过多,也可能导致内存泄漏,MySQL奔溃。

2. 数据库连接池种类

  1. JDBC的数据库连接池使用javax.sql.DataSource,DataSource是一个接口,该接口通常由第三方提供实现。
  2. C3P0数据库连接池,速度相对较慢,稳定性高。(Hibernate, Spring)
  3. DBCP数据库连接池,速度相对C3P0较快,但不稳定。
  4. Proxool数据库连接池,有监控连接池状态的功能,稳定性较C3P0差一些。
  5. BoneCP数据库连接池,速度快。
  6. Druid(德鲁伊)是由阿里提供的数据库连接池,集DBCP、C3P0、Proxool优点于一身的数据库连接池。

3. 使用案例

下面案例都会测试连接500000次,统计耗费时间。

3.1 C3P0案例

3.1.1 手动配置参数

使用这种方式,需要在代码中手动配置数据库连接池相关参数,代码量较大。代码如下:

@Test
public void testC3P0_1() throws Exception {
    // 获取值
    Properties properties = new Properties();
    properties.load(new FileInputStream("src\\mysql.properties"));
    String user = properties.getProperty("user");
    String password = properties.getProperty("password");
    String dirver = properties.getProperty("dirver");
    String url = properties.getProperty("url");

    // 设置相关参数
    ComboPooledDataSource dataSource = new ComboPooledDataSource();
    dataSource.setUser(user);
    dataSource.setPassword(password);
    dataSource.setDriverClass(dirver);
    dataSource.setJdbcUrl(url);
    // 初始化连接数
    dataSource.setInitialPoolSize(10);
    // 最大连接数
    dataSource.setMaxPoolSize(50);
    long start = System.currentTimeMillis();
    for (int i = 0; i < 500000; i++) {
        Connection connection = dataSource.getConnection();
        connection.close();
    }
    long end = System.currentTimeMillis();
    System.out.println("C3P0 500000次连接耗时:" + (end - start) / 1000.0 + "s");
}

本机耗时3.359s。运行结果如下:

【数据库编程】7.连接池_数据库连接池

3.1.2 使用配置文件

在src目录下创建一个文件c3p0-config.xml,文件内容如下:

<c3p0-config>
    <named-config name="c3p0_dataSource">
        <!-- 驱动类 -->
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <!-- URL -->
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/db02?rewriteBatchedStatements=true</property>
        <!-- 用户名 -->
        <property name="user">root</property>
        <!-- 密码 -->
        <property name="password">123456</property>
        <!-- 每次增长的连接数 -->
        <property name="acquireIncrement">5</property>
        <!-- 初始的连接数 -->
        <property name="initialPoolSize">10</property>
        <!-- 最小连接数 -->
        <property name="minPoolSize">5</property>
        <!-- 最大连接数 -->
        <property name="maxPoolSize">50</property>
        <!-- 可连接的最多的命令对象数 -->
        <property name="maxStatements">5</property>
        <!-- 每个连接对象可连接的最多的命令对象数 -->
        <property name="maxStatementsPerConnection">2</property>
    </named-config>
</c3p0-config>

此时代码量相较手动配置就会少很多,代码如下:

@Test
public void testC3P0_2() throws SQLException {
    ComboPooledDataSource dataSource = new ComboPooledDataSource("c3p0_dataSource");
    long start = System.currentTimeMillis();
    for (int i = 0; i < 500000; i++) {
        Connection connection = dataSource.getConnection();
        connection.close();
    }
    long end = System.currentTimeMillis();
    System.out.println("C3P0 500000次连接耗时:" + (end - start) / 1000.0 + "s");
}

本机耗时3.032s,两次结果接近。运行结果如下:

【数据库编程】7.连接池_数据库连接池_02

3.2 Druid案例

首先需要编写一个druid.properties(文件名随意)配置文件,内容如下:

diverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/db02?rewriteBatchedStatements=true
username=root
password=123456
# 初始连接数
initialSize=10
# 最小空闲连接数
minIdle=5
# 最大连接数
maxActive=20
# 最大等待时间,即超时时间,单位:毫秒
maxWait=5000

之后编写Java代码,测试连接500000耗费的时间,代码如下:

@Test
public void testDruid() throws Exception {
    // 读取配置
    Properties properties = new Properties();
    properties.load(new FileInputStream("src\\druid.properties"));

    DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
    long start = System.currentTimeMillis();
    for (int i = 0; i < 500000; i++) {
        Connection connection = dataSource.getConnection();
        connection.close();
    }
    long end = System.currentTimeMillis();
    System.out.println("C3P0 500000次连接耗时:" + (end - start) / 1000.0 + "s");
}

本机耗时0.814s,Druid速度相较C3P0速度有非常大的提升。运行结果如下:

【数据库编程】7.连接池_JDBC_03