数据库连接池的理解和使用

摘要:
简而言之,数据库连接池负责分配、管理和释放数据库连接。它允许应用程序重用现有数据库连接,而不是重新建立数据库连接。通过使用连接池,程序的运行效率将大大提高。同时,我们可以通过自己的管理机制来监控数据库连接的数量和使用情况。当客户端释放数据库连接时,首先确定对该连接的引用数是否超过指定值。如果数字超过指定值,请从连接池中删除连接。否则,它将保留给其他客户。

一、什么是数据库连接池?

官方:数据库连接池(Connection pooling)是程序启动时建立足够的数据库连接,并将这些连接组成一个连接池,由程序动态地对池中的连接进行申请,使用,释放。
个人理解:创建数据库连接是一个很耗时的操作,也容易对数据库造成安全隐患。所以,在程序初始化的时候,集中创建多个数据库连接,并把他们集中管理,供程序使用,可以保证较快的数据库读写速度,还更加安全可靠。

简而言之,数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个。

为什么要使用连接池
 数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出。  一个数据库连接对象均对应一个物理数据库连接,每次操作都打开一个物理连接,使用完都关闭连接,这样造成系统的 性能低下。 数据库连接池的解决方案是在应用程序启动时建立足够的数据库连接,并讲这些连接组成一个连接池(简单说:在一个“池”里放了好多半成品的数据库联接对象),由应用程序动态地对池中的连接进行申请、使用和释放。对于多于连接池中连接数的并发请求,应该在请求队列中排队等待。并且应用程序可以根据池中连接的使用率,动态增加或减少池中的连接数。 连接池技术尽可能多地重用了消耗内存地资源,大大节省了内存,提高了服务器地服务效率,能够支持更多的客户服务。通过使用连接池,将大大提高程序运行效率,同时,我们可以通过其自身的管理机制来监视数据库连接的数量、使用情况等。 

二、数据库连接池的运行机制

1.运行机制

(1) 程序初始化时创建连接池
(2) 使用时向连接池申请可用连接
(3) 使用完毕,将连接返还给连接池
(4) 程序退出时,断开所有连接,并释放资源
数据库连接池的理解和使用第1张

第一、连接池的建立。一般在系统初始化时,连接池会根据系统配置建立,并在池中创建了几个连接对象,以便使用时能从连接池中获取。连接池中的连接不能随意创建和关闭,这样避免了连接随意建立和关闭造成的系统开销。Java中提供了很多容器类可以方便的构建连接池,例如Vector、Stack等。

第二、连接池的管理。连接池管理策略是连接池机制的核心,连接池内连接的分配和释放对系统的性能有很大的影响。其管理策略是:

        当客户请求数据库连接时,首先查看连接池中是否有空闲连接,如果存在空闲连接,则将连接分配给客户使用;如果没有空闲连接,则查看当前所开的连接数是否已经达到最大连接数,如果没达到就重新创建一个连接给请求的客户;如果达到就按设定的最大等待时间进行等待,如果超出最大等待时间,则抛出异常给客户。

        当客户释放数据库连接时,先判断该连接的引用次数是否超过了规定值,如果超过就从连接池中删除该连接,否则保留为其他客户服务。

        该策略保证了数据库连接的有效复用,避免频繁的建立、释放连接所带来的系统资源开销。

第三、连接池的关闭。当应用程序退出时,关闭连接池中所有的连接,释放连接池相关的资源,该过程正好与创建相反。

2.连接池主要参数

使用连接池时,要配置一下参数

(1)最小连接数:是连接池一直保持的数据库连接,所以如果应用程序对数据库连接的使用量不大,将会有大量的数据库连接资源被浪费.
(2)最大连接数:是连接池能申请的最大连接数,如果数据库连接请求超过次数,后面的数据库连接请求将被加入到等待队列中,这会影响以后的数据库操作
(3)最大空闲时间
(4)获取连接超时时间
(5)超时重试连接次数

        dataSource.setInitialPoolSize(5); //初始化连接数
        dataSource.setMinPoolSize(1);//最小连接数
        dataSource.setMaxPoolSize(10);//最大连接数
        dataSource.setMaxStatements(50);//最长等待时间
        dataSource.setMaxIdleTime(60);//最大空闲时间,单位毫秒  
三、数据库连接池种类及性能

开源数据库连接池:
1 dbcp
dbcp可能是使用最多的开源连接池,这个连接池可以设置最大和最小连接,连接等待时间等,基本功能都有。
优缺点:稳定性还是可以,不过速度稍慢,在大并发量的压力下稳定性有所下降,此外不提供连接池监控
2 c3p0
c3p0是另外一个开源的连接池,在业界也是比较有名的,这个连接池可以设置最大和最小连接,连接等待时间等,基本功能都有。

优缺点:连接池的持续运行的稳定性相当不错,在大并发量的压力下稳定性也有一定保证,此外不提供连接池监控。
3 proxool
proxool这个连接池可能用到的人比较少,但也有一定知名度,这个连接池可以设置最大和最小连接,连接等待时间等,基本功能都有。

优缺点:稳定性有一定问题,有一个需要长时间跑批的任务场景任务,优势--连接池监控

4.Druid

Druid是Java语言中最好的数据库连接池。Druid能够提供强大的监控和扩展功能。

四、数据库连接池的使用

作为开源的数据库连接池,C3P0是一个优秀的连接池,性能也十分可靠。

首先到http://sourceforge.net/projects/c3p0/下载相应的jar包,总共三个,如下图所示。

 数据库连接池的理解和使用第2张

其次将jar包导入到工程当中,然后就可以使用cp30了。

示例代码如下:

package com.zww.server;
 
import java.beans.PropertyVetoException;
import java.sql.Connection;
import java.sql.SQLException;
import com.mchange.v2.c3p0.ComboPooledDataSource;
 
public final class ConnectionManager {
	//使用单利模式创建数据库连接池
    private static ConnectionManager instance;
    private static ComboPooledDataSource dataSource;
 
    private ConnectionManager() throws SQLException, PropertyVetoException {
        dataSource = new ComboPooledDataSource();
 
        dataSource.setUser("root");		//用户名
        dataSource.setPassword("123456"); //密码
        dataSource.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/zww");//数据库地址
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        dataSource.setInitialPoolSize(5); //初始化连接数
        dataSource.setMinPoolSize(1);//最小连接数
        dataSource.setMaxPoolSize(10);//最大连接数
        dataSource.setMaxStatements(50);//最长等待时间
        dataSource.setMaxIdleTime(60);//最大空闲时间,单位毫秒
    }
 
    public static final ConnectionManager getInstance() {
        if (instance == null) {
            try {
                instance = new ConnectionManager();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return instance;
    }
 
    public synchronized final Connection getConnection() {
        Connection conn = null;
        try {
            conn = dataSource.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }
}

  下面是测试代码:

package com.zww.server;
 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
 
 
public class ConnectionDemo {
 
    public static void main(String[] args) throws SQLException {
        System.out.println("使用连接池................................");
        for (int i = 0; i < 20; i++) {
            long beginTime = System.currentTimeMillis();
            Connection conn = ConnectionManager.getInstance().getConnection();
            try {
                PreparedStatement pstmt = conn.prepareStatement("select * from event");
                ResultSet rs = pstmt.executeQuery();
                while (rs.next()) {
                	 // do nothing...
                }
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
 
            long endTime = System.currentTimeMillis();
            System.out.println("第" + (i + 1) + "次执行花费时间为:" + (endTime - beginTime));
        }
 
        System.out.println("不使用连接池................................");
        for (int i = 0; i < 20; i++) {
            long beginTime = System.currentTimeMillis();
           	MysqlDataSource mds = new MysqlDataSource();
           	mds.setURL("jdbc:mysql://localhost:3306/zww");
            mds.setUser("root");
            mds.setPassword("123456");
            Connection conn = mds.getConnection();
            try {
                PreparedStatement pstmt = conn.prepareStatement("select * from event");
                ResultSet rs = pstmt.executeQuery();
                while (rs.next()) {
                                    // do nothing...
                }
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            long endTime = System.currentTimeMillis();
            System.out.println("第" + (i + 1) + "次执行花费时间为:"
                                + (endTime - beginTime));
        }
 
    }

  运行结果如下图所示:

数据库连接池的理解和使用第3张

 测试结果表明,在使用连接池时,只在第一次初始化时,比较耗时,完成初始化之后,使用连接池进行数据库操作明显比不使用连接池花费的时间少。

免责声明:文章转载自《数据库连接池的理解和使用》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇abap将内表数据导出为excel文件精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Linux 监控tcp连接数及状态

一、查看哪些IP连接本机 netstat -an 二、查看TCP连接数 查看tcp连接数状态   netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'  统计8080端口上有多少个TCP连接,命令:   netstat -ant |grep 80|wc -l  TCP连接中...

解决XP在网络中最大共享连接数的问题

解决XP在网络中最大共享连接数的问题 XP默认并发数是10,若考虑用XP做文件服务器,只能修改TCP/IP并发数方案一:解决方案找一个更改连接数量的软件XP_SP2_TCPIP_Patch.exe下载:http://www.stu-shop.com/upload/XP_SP2_TCPIP_Patch.exe该补丁可把最大连接数修改为255,满足一般...

QPS、CPS、最大连接数

QPS、CPS、最大连接数概念 最大连接数-Max Connection最大连接数定义了一个负载均衡实例能够承载的最大连接数量。当实例上的连接超过规格定义的最大连接数时,新建连接请求将被丢弃。 每秒新建连接数-Connection Per Second (CPS)每秒新建连接数定义了新建连接的速率。当新建连接的速率超过规格定义的每秒新建连接数时,新建连接请...

关于.NET大数据量大并发量的数据连接池管理 Virus

首先声明,本人以前做的都是小应用,还没有设计过百万、千万数据量的应用,并发量上万的应用,很多时候都是Applicatiion Server和DB Server在一台机器,或者将DB Server分离出来,单独在一台机器。由于最近的工作需要,故产生很多疑问,想要和大家一起探讨,向大家学习,希望大家不吝赐教,感谢大家的参与。 首先提一下本文的需求来源和具体的...

Java创建数据库连接池(两种方式)

提供数据库连接池:作用是提供动态的连接闭合状态(即用即开、不用即关、提高效率)              提供两个静态方法:①OpenConn()②CloseConn(Connection conn)1.使用Propertie对象获取数据库配置文件(即Jdbc.properties)提供的配置信息以供给第二步使用2.数据库目前我了解的有两种创建连接的方式=...

DNS解析过程和域名收敛、域名发散、SPDY应用

前段时间项目要做域名收敛,糊里糊涂的完成了,好多原理不清晰,现在整理搜集下知识点。 域名收敛的目的是什么?简单来说就是域名解析慢。那为什么解析慢?且听下文慢慢道来。 什么是DNS?  DNS( Domain Name System)是“域名系统”的英文缩写,是一种组织成域层次结构的计算机和网络服务命名系统,它用于TCP/IP网络,它所提供的服务是用来将主机...