返回顶部
首页 > 资讯 > 数据库 >数据库连接池的方式有哪几种
  • 117
分享到

数据库连接池的方式有哪几种

2024-04-02 19:04:59 117人浏览 薄情痞子
摘要

这篇文章主要讲解了“数据库连接池的方式有哪几种”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“数据库连接池的方式有哪几种”吧! 一、介绍数据库连接是

这篇文章主要讲解了“数据库连接池的方式有哪几种”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“数据库连接池的方式有哪几种”吧!

数据库连接池的方式有哪几种

 一、介绍

数据库连接是一项非常关键的、有限的、昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出。

记得之前做的一个项目,当时的应用程序配置的c3p0数据库连接池,最大允许的连接数是500,结果上线没多久,并发量直接上来了,导致大量的数据插入失败,当晚的心情可想而知~

从那一次事故之后,让我对应用程序的数据库连接数有了一次深刻的认识,为了防止再次栽跟头,特意抽了一个时间来编写程序测试案例,用于测试各个数据源连接池的稳定性,以防止自己再次踩坑!

话不多说,直接撸起来!

二、程序实例

熟悉 WEB 系统开发的同学,基本都知道,在 Java 生态中开源的常用数据库连接池有以下几种:

  • dbcp:DBCP是一个依赖Jakarta  commons-pool对象池机制的数据库连接池,DBCP可以直接的在应用程序中使用,Tomcat的数据源使用的就是DBCP

  • c3p0:c3p0是一个开放源代码的JDBC连接池,它在lib目录中与Hibernate一起发布,包括了实现jdbc3和jdbc2扩展规范说明的Connection和Statement池的DataSources对象

  • druid:阿里出品,淘宝和支付宝专用数据库连接池,但它不仅仅是一个数据库连接池,它还包含一个ProxyDriver,一系列内置的JDBC组件库,一个sql  Parser。支持所有JDBC兼容的数据库,包括oracleMysql、Derby、postgresqlSQL Server、H2等等。

今天我们就一起来对比一下,这三种数据源连接池的稳定性。

2.1、创建测试表

下面以 mysql 数据库为例,首先创建一个t_test表,方面后续进行插入数据操作。

CREATE TABLE t_test (   id bigint(20) unsigned NOT NULL COMMENT '主键ID',   name varchar(32) NOT NULL COMMENT '名称',   PRIMARY KEY (id) ) ENGINE=InnoDB COMMENT='测试表';

2.2、 编写测试用例

以dbcp为例,首先创建一个dbcp-jdbc.properties配置文件。

username=root passWord=Hello@123456 driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql://192.168.31.200:3306/testdb?useUnicode=true&characterEncoding=UTF-8 initialSize=5 maxActive=1000 maxIdle=5 removeAbandoned=ture removeAbandonedTimeout=20 logAbandoned=true maxWait=100

接着,创建一个连接池工具DbcpJdbcUtil。

public class DbcpJdbcUtil {    private static final Logger logger = LoggerFactory.getLogger(DbcpJdbcUtil.class);      private static Properties prop = new Properties();     private static BasicDataSource dataSource = null;  // 它是事务专用连接!  private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();    static {   classPathSourceRead();  }      private static void classPathSourceRead(){      //读取指定位置的配置文档(读取class目录文件)      try {       logger.info("jdbc路径:" + SysConstants.getValue());    prop.load(DbcpJdbcUtil.class.getClassLoader().getResourceAsStream(SysConstants.getValue()));    logger.info("数据配置信息" + JSON.tojsONString(prop));    logger.info("初始化默认jdbc配置文件成功!");   } catch (Exception e) {    logger.error("初始化默认jdbc文件失败!",e);   }     }         public static BasicDataSource getDataSource() throws Exception {   try {    if (dataSource == null) {     synchronized (DbcpJdbcUtil.class) {      if (dataSource == null) {       dataSource = new BasicDataSource();       dataSource.setUsername(prop.getProperty("username"));       dataSource.setPassword(prop.getProperty("password"));       dataSource.setDriverClassName(prop.getProperty("driverClassName"));       dataSource.setUrl(prop.getProperty("url"));       dataSource.setInitialSize(Integer.valueOf(prop.getProperty("initialSize")));       dataSource.setMaxActive(Integer.valueOf(prop.getProperty("maxActive")));       dataSource.setMaxIdle(Integer.valueOf(prop.getProperty("maxIdle")));       dataSource.setRemoveAbandoned(Boolean.valueOf(prop.getProperty("removeAbandoned")));       dataSource.setRemoveAbandonedTimeout(Integer.valueOf(prop.getProperty("removeAbandonedTimeout")));       dataSource.setLogAbandoned(Boolean.valueOf(prop.getProperty("logAbandoned")));       dataSource.setMaxWait(Integer.valueOf(prop.getProperty("maxWait")));      }     }    }    return dataSource;   } catch (Exception e) {    logger.error("根据数据库名称获取数据库资源失败," , e);    throw new Exception("根据数据库名称获取数据库资源失败");   }  }      public static Connection getConnection() throws Exception {   try {    Connection con = tl.get();    // 当con不等于null,说明已经调用过beginTransaction(),表示开启了事务!    if (con != null)     return con;    return getDataSource().getConnection();   } catch (Exception e) {    logger.error("获取数据库连接失败!", e);    throw new SQLException("获取数据库连接失败!");   }  }      public static void beginTransaction() throws Exception {   try {    Connection con = tl.get();    if (con != null) {     con.close();     tl.remove();     //throw new SQLException("已经开启了事务,就不要重复开启了!");    }    con = getConnection();    con.setAutoCommit(false);    tl.set(con);   } catch (Exception e) {    logger.error("数据库事物开启失败!", e);    throw new SQLException("数据库事物开启失败!");   }  }     public static void commitTransaction() throws SQLException {   Connection con = tl.get();   try {    if (con == null)     throw new SQLException("还没有开启事务,不能提交!");    con.commit();   } catch (Exception e) {    logger.error("数据库事物提交失败!", e);    throw new SQLException("数据库事物提交失败!");   } finally {    if (con != null) {     con.close();    }    tl.remove();   }  }      public static void rollbackTransaction() throws SQLException {   Connection con = tl.get();   try {    if (con == null)     throw new SQLException("还没有开启事务,不能回滚!");    con.rollback();   } catch (Exception e) {    logger.error("数据库事物回滚失败!", e);    throw new SQLException("数据库事物回滚失败!");   } finally {    if (con != null) {     con.close();    }    tl.remove();   }  }      public static void releaseConnection(Connection connection) throws SQLException {   try {    Connection con = tl.get();    // 判断它是不是事务专用,如果是,就不关闭! 如果不是事务专用,那么就要关闭!    // 如果con == null,说明现在没有事务,那么connection一定不是事务专用的!    //如果con != null,说明有事务,那么需要判断参数连接是否与con相等,若不等,说明参数连接不是事务专用连接    if (con == null || con != connection)     connection.close();   } catch (Exception e) {    logger.error("数据库连接释放失败!", e);    throw new SQLException("数据库连接释放失败!");   }  }  }

最后,编写单元测试程序DBCPTest。

public class DBCPTest {    private static final int sumCount = 1000000;    private static final int threadNum = 600;    private void before(String path) {   SysConstants.putValue(path);   new DBCPService().insert("delete from t_test");  }    @Test  public void testMysql() {   long start = System.currentTimeMillis();   String path = "config/mysql/dbcp-jdbc.properties";   before(path);   for (int i =0; i < 1; i++) {    String sql = "insert into t_test(id,name) values('" +i+ "','dbcp-mysql-" + i + "')";    new DBCPService().insert(sql);   }   System.out.println("耗时:" + (System.currentTimeMillis() - start));  }    @Test  public void testThreadMysql() throws InterruptedException {   String path = "config/mysql/dbcp-jdbc.properties";   before(path);   BlockingQueue<String> queue = new LinkedBlockingQueue<String>();   for (int i = 0; i < sumCount; i++) {    String sql = "insert into t_test(id,name) values('" +i+ "','dbcp-mysql-" + i + "')";    queue.put(sql);   }   long start = System.currentTimeMillis();   final CountDownLatch countDownLatch = new CountDownLatch(threadNum);   for (int i = 0; i < threadNum; i++) {    final int finalI = i + 1;    new Thread(new Runnable() {     @Override     public void run() {      System.out.println("thread " + finalI + " start");      boolean isGo = true;      while (isGo) {       String sql = queue.poll();       if(sql != null) {        new DBCPService().insert(sql);       }else {        isGo =false;        System.out.println("thread " + finalI + " finish");        countDownLatch.countDown();       }      }     }    }).start();   }   countDownLatch.await();    System.out.println("耗时:" + (System.currentTimeMillis() - start));  }  }

c3p0、druid的配置也类似,这里就不在重复介绍了!

三、性能测试

程序编写完成之后,下面我们就一起来结合各种不同的场景来测试一下各个数据连接池的表现。

为了进一步扩大测试范围,本次测试还将各个主流的数据库也拉入进去,测试的数据库分别是:mysql-5.7、oracle-12、postgresql-9.6

3.1、插入10万条数据

首先,我们来测试一下,各个数据库插入10万条数据,采用不同的数据源连接池,看看它们的表现如何?

  • 测试dbcp执行结果

数据库连接池的方式有哪几种

  • 测试c3p0执行结果

数据库连接池的方式有哪几种

测试druid执行结果

数据库连接池的方式有哪几种

从上面测试结果,我们可以基本得出如下结论:

  • 从数据连接池性能角度看:dbcp >= druid > c3p0

  • 从数据库性能角度看:oracle > postgresql > mysql

其中druid对postgresql的支持性能最好,c3p0的表现比较差!

3.2、插入100万条数据

可能有的同学,还不太认可,下面我们就来测试一下插入100万条,看看它们的表现如何?

  • 测试dbcp执行结果

数据库连接池的方式有哪几种

  • 测试c3p0执行结果

数据库连接池的方式有哪几种

  • 测试druid执行结果

数据库连接池的方式有哪几种

从上面测试结果,我们可以基本得出如下结论:

  • 从数据连接池性能角度看:druid性能比较稳定,dbcp、c3p0都有某种程度的执行失败

  • 从数据库性能角度看:postgresql > oracle > mysql

还是一样的结论,druid对postgresql的支持性能最好,c3p0的表现比较差!

四、小结

从上面的测试结果,我们可以很清晰的看到,在数据连接池方面,druid和dbcp旗鼓相当,而并发方面druid的稳定性大于dbcp,c3p0相比druid和dbcp,稳定性和执行速度要弱些。

在数据库方面,postgresql速度要优于oracle,而oracle对各个数据源的支持和稳定性要有优势,mysql相比oracle和postgresql,执行速度要弱些。

如果在实际开发中,数据源连接池推荐采用druid,数据库的选用方面 postgresql > oracle > mysql。

感谢各位的阅读,以上就是“数据库连接池的方式有哪几种”的内容了,经过本文的学习后,相信大家对数据库连接池的方式有哪几种这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

您可能感兴趣的文档:

--结束END--

本文标题: 数据库连接池的方式有哪几种

本文链接: https://lsjlt.com/news/61537.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 数据库连接池的方式有哪几种
    这篇文章主要讲解了“数据库连接池的方式有哪几种”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“数据库连接池的方式有哪几种”吧! 一、介绍数据库连接是...
    99+
    2024-04-02
  • oracle数据库连接方式有哪几种
    Oracle数据库连接方式有以下几种:1. 使用SQL*Plus连接:SQL*Plus是Oracle数据库自带的一个命令行工具,可以...
    99+
    2023-10-12
    oracle数据库
  • spring创建连接池的几种方式
    spring使用连接池有很多种方式,jdbc(不使用连接池),c3p0,dbcp,jndi,下面将分别贴代码介绍这几种: 1.jdbc方式   使用的是DriverManage...
    99+
    2024-04-02
  • oracle表连接的方式有哪几种
    内连接(INNER JOIN):返回两个表中符合连接条件的记录。 外连接(OUTER JOIN):包括左外连接(LEFT J...
    99+
    2024-04-09
    oracle
  • Java中几种常用数据库连接池的使用
    目录一、应用程序直接获取数据库连接的缺点二、使用数据库连接池优化程序性能2.1、数据库连接池的基本概念2.2、编写数据库连接池三、开源数据库连接池3.1、DBCP数据源3.2、在应用...
    99+
    2024-04-02
  • sqlplus连接数据库的几种方法
    1. sqlplus / as sysdba     操作系统认证,不需要数据库服务器启动listener,也不需要数据库服务器处于可用状态。比如我们想要启动数据库就可以用这种方式...
    99+
    2024-04-02
  • C#连接数据库的几种方法
    一、Oracle 查询 public static DataTable QueryData() { DataTable dtResult = new ...
    99+
    2024-04-02
  • ASP连接Access数据库的几种方法
    在ASP中连接Access数据库有以下几种方法:1. 使用OLEDB连接字符串:```<%Dim ConnSet Conn =...
    99+
    2023-08-15
    ASP
  • oracle数据库备份方式有哪几种
    数据库级备份:完整备份整个数据库,包括数据文件、控制文件、归档日志等。 表级备份:备份指定的表或表空间,可以选择性备份数据库中的部...
    99+
    2024-04-09
    oracle
  • 数据库连接方式有哪些
    小编给大家分享一下数据库连接方式有哪些,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!在建立Oracle数据库的时候,应该会在数据...
    99+
    2024-04-02
  • MySQL连接数据库的方式有哪些
    MySQL连接数据库的方式有以下几种:1. 使用命令行连接:在命令行窗口中使用mysql命令连接数据库,例如:mysql -h 主机...
    99+
    2023-09-09
    MySQL 数据库
  • 数据库连接池
    连接池是管理数据库连接的一种机制,能够控制连接的个数,默认情况下可以预先创建可用的连接。有四种常见的连接池框架1、Apache的DBCP连接池(Tomcat内置了DBCP)2、C3P0连接池3、proxco...
    99+
    2024-04-02
  • 数据库常用的几种入侵的方式有哪些
    今天就跟大家聊聊有关数据库常用的几种入侵的方式有哪些,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。随着互联网的高速发展,越来越多的企业搭乘着互联网这班高速列车使得自己的企业发展的越来...
    99+
    2023-06-07
  • PHP中有哪些连接数据库的方式
    本篇文章给大家分享的是有关PHP中有哪些连接数据库的方式,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。PHP连接数据库之PHP连接MYSQL数据库代码< php...
    99+
    2023-06-17
  • python连接clickhouse数据库的方式有哪些
    这篇文章主要介绍“python连接clickhouse数据库的方式有哪些”,在日常操作中,相信很多人在python连接clickhouse数据库的方式有哪些问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”pyt...
    99+
    2023-06-30
  • java连接oracle数据库的方式有哪些
    使用JDBC连接:可以通过JDBC(Java Database Connectivity)来连接Oracle数据库。首先需要下载...
    99+
    2024-04-09
    java oracle
  • mysql数据库删除表数据的方式有几种
    这篇文章将为大家详细讲解有关mysql数据库删除表数据的方式,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。在MySQL中删除数据有两种方式:1、truncate(截短)属...
    99+
    2024-04-02
  • 常见数据库连接方式有哪些
    这篇文章给大家分享的是有关常见数据库连接方式有哪些的内容。小编觉得挺实用的,因此分享给大家做个参考。一起跟随小编过来看看吧。1.Access数据库的DSN-less连接方法:set adocon=Serve...
    99+
    2024-04-02
  • 数据库中表连接方式有哪些
    这篇文章将为大家详细讲解有关数据库中表连接方式有哪些,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。 1 nested loop join 循...
    99+
    2024-04-02
  • 【LISTENER】数据库连接串的几种写法
    第一种,service_name,oracle11g rac scan ip可以使用如下,如果想用vip,就写两个地址,如红色部分 点击(此处)折叠或打开 ...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作