欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

數(shù)據(jù)庫連接池的方式有哪幾種

這篇文章主要講解了“數(shù)據(jù)庫連接池的方式有哪幾種”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“數(shù)據(jù)庫連接池的方式有哪幾種”吧!

專業(yè)成都網(wǎng)站建設公司,做排名好的好網(wǎng)站,排在同行前面,為您帶來客戶和效益!創(chuàng)新互聯(lián)為您提供成都網(wǎng)站建設,五站合一網(wǎng)站設計制作,服務好的網(wǎng)站設計公司,網(wǎng)站建設、網(wǎng)站制作負責任的成都網(wǎng)站制作公司!

數(shù)據(jù)庫連接池的方式有哪幾種

 一、介紹

數(shù)據(jù)庫連接是一項非常關鍵的、有限的、昂貴的資源,這一點在多用戶的網(wǎng)頁應用程序中體現(xiàn)得尤為突出。

記得之前做的一個項目,當時的應用程序配置的c3p0數(shù)據(jù)庫連接池,最大允許的連接數(shù)是500,結果上線沒多久,并發(fā)量直接上來了,導致大量的數(shù)據(jù)插入失敗,當晚的心情可想而知~

從那一次事故之后,讓我對應用程序的數(shù)據(jù)庫連接數(shù)有了一次深刻的認識,為了防止再次栽跟頭,特意抽了一個時間來編寫程序測試案例,用于測試各個數(shù)據(jù)源連接池的穩(wěn)定性,以防止自己再次踩坑!

話不多說,直接擼起來!

二、程序實例

熟悉 web 系統(tǒng)開發(fā)的同學,基本都知道,在 Java 生態(tài)中開源的常用數(shù)據(jù)庫連接池有以下幾種:

  • dbcp:DBCP是一個依賴Jakarta  commons-pool對象池機制的數(shù)據(jù)庫連接池,DBCP可以直接的在應用程序中使用,Tomcat的數(shù)據(jù)源使用的就是DBCP

  • c3p0:c3p0是一個開放源代碼的JDBC連接池,它在lib目錄中與Hibernate一起發(fā)布,包括了實現(xiàn)jdbc3和jdbc2擴展規(guī)范說明的Connection和Statement池的DataSources對象

  • druid:阿里出品,淘寶和支付寶專用數(shù)據(jù)庫連接池,但它不僅僅是一個數(shù)據(jù)庫連接池,它還包含一個ProxyDriver,一系列內置的JDBC組件庫,一個SQL  Parser。支持所有JDBC兼容的數(shù)據(jù)庫,包括Oracle、MySQL、Derby、Postgresql、SQL Server、H2等等。

今天我們就一起來對比一下,這三種數(shù)據(jù)源連接池的穩(wěn)定性。

2.1、創(chuàng)建測試表

下面以 mysql 數(shù)據(jù)庫為例,首先創(chuàng)建一個t_test表,方面后續(xù)進行插入數(shù)據(jù)操作。

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為例,首先創(chuàng)建一個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

接著,創(chuàng)建一個連接池工具DbcpJdbcUtil。

public class DbcpJdbcUtil {    private static final Logger logger = LoggerFactory.getLogger(DbcpJdbcUtil.class);    /**jdbc配置文件*/  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("數(shù)據(jù)配置信息" + JSON.toJSONString(prop));    logger.info("初始化默認jdbc配置文件成功!");   } catch (Exception e) {    logger.error("初始化默認jdbc文件失敗!",e);   }     }       /**   * 從連接池獲取數(shù)據(jù)源   * @return   * @throws Exception   */  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("根據(jù)數(shù)據(jù)庫名稱獲取數(shù)據(jù)庫資源失敗," , e);    throw new Exception("根據(jù)數(shù)據(jù)庫名稱獲取數(shù)據(jù)庫資源失敗");   }  }    /**   * 使用連接池返回一個連接對象   *    * @return   * @throws SQLException   */  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("獲取數(shù)據(jù)庫連接失??!", e);    throw new SQLException("獲取數(shù)據(jù)庫連接失??!");   }  }    /**   * 開啟事務 1. 獲取一個Connection,設置它的setAutoComnmit(false)    * 2. 還要保證dao中使用的連接是我們剛剛創(chuàng)建的! --------------    * 3. 創(chuàng)建一個Connection,設置為手動提交    * 4. 把這個Connection給dao用!    * 5. 還要讓commitTransaction或rollbackTransaction可以獲取到!   *    * @throws 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("數(shù)據(jù)庫事物開啟失?。?quot;, e);    throw new SQLException("數(shù)據(jù)庫事物開啟失?。?quot;);   }  }   /**   * 提交事務 1. 獲取beginTransaction提供的Connection,然后調用commit方法   *    * @throws 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("數(shù)據(jù)庫事物提交失敗!", e);    throw new SQLException("數(shù)據(jù)庫事物提交失敗!");   } finally {    if (con != null) {     con.close();    }    tl.remove();   }  }    /**   * 回滾事務 1. 獲取beginTransaction提供的Connection,然后調用rollback方法   *    * @throws SQLException   */  public static void rollbackTransaction() throws SQLException {   Connection con = tl.get();   try {    if (con == null)     throw new SQLException("還沒有開啟事務,不能回滾!");    con.rollback();   } catch (Exception e) {    logger.error("數(shù)據(jù)庫事物回滾失??!", e);    throw new SQLException("數(shù)據(jù)庫事物回滾失敗!");   } finally {    if (con != null) {     con.close();    }    tl.remove();   }  }    /**   * 釋放連接    * @param connection   * @throws SQLException   */  public static void releaseConnection(Connection connection) throws SQLException {   try {    Connection con = tl.get();    // 判斷它是不是事務專用,如果是,就不關閉! 如果不是事務專用,那么就要關閉!    // 如果con == null,說明現(xiàn)在沒有事務,那么connection一定不是事務專用的!    //如果con != null,說明有事務,那么需要判斷參數(shù)連接是否與con相等,若不等,說明參數(shù)連接不是事務專用連接    if (con == null || con != connection)     connection.close();   } catch (Exception e) {    logger.error("數(shù)據(jù)庫連接釋放失??!", e);    throw new SQLException("數(shù)據(jù)庫連接釋放失敗!");   }  }  }

最后,編寫單元測試程序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的配置也類似,這里就不在重復介紹了!

三、性能測試

程序編寫完成之后,下面我們就一起來結合各種不同的場景來測試一下各個數(shù)據(jù)連接池的表現(xiàn)。

為了進一步擴大測試范圍,本次測試還將各個主流的數(shù)據(jù)庫也拉入進去,測試的數(shù)據(jù)庫分別是:mysql-5.7、oracle-12、postgresql-9.6

3.1、插入10萬條數(shù)據(jù)

首先,我們來測試一下,各個數(shù)據(jù)庫插入10萬條數(shù)據(jù),采用不同的數(shù)據(jù)源連接池,看看它們的表現(xiàn)如何?

  • 測試dbcp執(zhí)行結果

數(shù)據(jù)庫連接池的方式有哪幾種

  • 測試c3p0執(zhí)行結果

數(shù)據(jù)庫連接池的方式有哪幾種

測試druid執(zhí)行結果

數(shù)據(jù)庫連接池的方式有哪幾種

從上面測試結果,我們可以基本得出如下結論:

  • 從數(shù)據(jù)連接池性能角度看:dbcp >= druid > c3p0

  • 從數(shù)據(jù)庫性能角度看:oracle > postgresql > mysql

其中druid對postgresql的支持性能最好,c3p0的表現(xiàn)比較差!

3.2、插入100萬條數(shù)據(jù)

可能有的同學,還不太認可,下面我們就來測試一下插入100萬條,看看它們的表現(xiàn)如何?

  • 測試dbcp執(zhí)行結果

數(shù)據(jù)庫連接池的方式有哪幾種

  • 測試c3p0執(zhí)行結果

數(shù)據(jù)庫連接池的方式有哪幾種

  • 測試druid執(zhí)行結果

數(shù)據(jù)庫連接池的方式有哪幾種

從上面測試結果,我們可以基本得出如下結論:

  • 從數(shù)據(jù)連接池性能角度看:druid性能比較穩(wěn)定,dbcp、c3p0都有某種程度的執(zhí)行失敗

  • 從數(shù)據(jù)庫性能角度看:postgresql > oracle > mysql

還是一樣的結論,druid對postgresql的支持性能最好,c3p0的表現(xiàn)比較差!

四、小結

從上面的測試結果,我們可以很清晰的看到,在數(shù)據(jù)連接池方面,druid和dbcp旗鼓相當,而并發(fā)方面druid的穩(wěn)定性大于dbcp,c3p0相比druid和dbcp,穩(wěn)定性和執(zhí)行速度要弱些。

在數(shù)據(jù)庫方面,postgresql速度要優(yōu)于oracle,而oracle對各個數(shù)據(jù)源的支持和穩(wěn)定性要有優(yōu)勢,mysql相比oracle和postgresql,執(zhí)行速度要弱些。

如果在實際開發(fā)中,數(shù)據(jù)源連接池推薦采用druid,數(shù)據(jù)庫的選用方面 postgresql > oracle > mysql。

感謝各位的閱讀,以上就是“數(shù)據(jù)庫連接池的方式有哪幾種”的內容了,經過本文的學習后,相信大家對數(shù)據(jù)庫連接池的方式有哪幾種這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關知識點的文章,歡迎關注!

分享標題:數(shù)據(jù)庫連接池的方式有哪幾種
文章源于:http://aaarwkj.com/article8/igssip.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站內鏈、用戶體驗、建站公司軟件開發(fā)外貿網(wǎng)站建設、全網(wǎng)營銷推廣

廣告

聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站托管運營
日本女优邻居人妻中文字幕| 久久精品国产亚洲av麻| 中文字幕精品人妻丝袜| 日韩中文字幕乱码一区| 欧美日韩一区中文字幕| 抱着操才爽的免费视频观看| 欧美日韩黄片免费在线观看| 亚洲综合一区二区三区不卡| 色橹橹欧美午夜精品福利| 91色老久久精品偷偷鲁无毒| 精品偷拍污视频一区二区| 欧美日韩亚洲国产激情| 欧美生活一区二区三区| 国产H精品在线观看| 蜜桃臀视频一区二区三区| 午夜精品人妻一区二区| 高清日本一区二区三区不卡片| 亚洲精品一区二区三区色| 天天干夜夜泡天天操| 日本一区二区中文字幕视频| 国产成人精品一区二区国产乱码| av第一福利大全导航| 亚洲新大香蕉视频在线播放| 成人中文字幕av电影| 国产91日韩欧美在线| 亚洲av无毛在线观看| 国产婷婷色三区一区二区| 久久国产精品99久久久| 一区二区三区在线观看日韩| 天天操天天日天天干夜夜情欢| 亚洲欧美精品一中文字幕| 三级久久三级久久三级| 人人人妻人人澡人人爽e| 亚洲欧美中文日韩二区一区| 国产日韩亚洲欧美色片| 最近av中文字幕电影| 国产一级黄色性生活片| 中日韩一二三四区在线看| 色婷婷亚洲婷婷亚洲最大| 97超碰97资源在线| 粉嫩av一男战三女高潮|