數(shù)據(jù)庫連接池

# 數(shù)據(jù)庫連接池

### 什么是連接池

數(shù)據(jù)庫連接池負責<font color='red'>分配蝶押、管理和釋放數(shù)據(jù)庫連接</font>狭园,它允許應(yīng)用程序<font color='red'>重復使用</font>一個現(xiàn)有的數(shù)據(jù)庫連接沙咏,<font color='orange'>而不是再重新建立一個</font>

### 為什么要用連接池

一個數(shù)據(jù)庫連接對象均對應(yīng)一個物理數(shù)據(jù)庫連接宴胧,每次操作都打開一個物理連接晶姊,使用完都關(guān)閉連接,<font color='cornflowerblue'>這樣造成系統(tǒng)的性能低下</font>崩瓤。

![img](池.assets/1606768-20190616155729169-544894466.png)

數(shù)據(jù)庫連接池的解決方案是在應(yīng)用程序啟動時建立足夠的數(shù)據(jù)庫連接袍啡,并講這些連接組成一個連接池,由應(yīng)用程序動態(tài)地對池中的連接進行申請却桶、使用和釋放境输。

<font color='red'>連接池技術(shù)盡可能多地重用了消耗內(nèi)存地資源,大大節(jié)省了內(nèi)存颖系,提高了服務(wù)器地服務(wù)效率嗅剖,能夠支持更多的客戶服務(wù)。</font>通過使用連接池嘁扼,將<font color='orange'>大大提高程序運行效率</font>信粮,同時,我們可以通過其自身的管理機制來監(jiān)視數(shù)據(jù)庫連接的數(shù)量趁啸、使用情況等强缘。

### 數(shù)據(jù)庫連接池接口

Java 為數(shù)據(jù)庫連接池提供了公共接口:<font color='red'>javax.sql.DataSource</font>,各大廠商可以讓自己的連接池實現(xiàn)該接口不傅,而應(yīng)用程序可以方便的切換不同的連接池旅掂。

### 數(shù)據(jù)庫連接池的優(yōu)點

- <font color='red'>資源重用</font>

? 由于數(shù)據(jù)庫連接得到重用,避免了頻繁創(chuàng)建访娶、釋放連接引起的大量性能開銷商虐。在減少系統(tǒng)消耗的基礎(chǔ)上,另一方面也增進了系統(tǒng)運行環(huán)境的平穩(wěn)性(減少內(nèi)存碎片以及數(shù)據(jù)庫臨時進程/線程的數(shù)量)崖疤。

- <font color='red'>更快的系統(tǒng)響應(yīng)速度</font>

? 數(shù)據(jù)庫連接池在初始化過程中秘车,往往已經(jīng)創(chuàng)建了若干數(shù)據(jù)庫連接置于池中備用。此時連接的初始化工作均已完成戳晌。對于業(yè)務(wù)請求處理而言鲫尊,直接利用現(xiàn)有可用連接,避免了數(shù)據(jù)庫連接初始化和釋放過程的時間開銷沦偎,從而縮減了系統(tǒng)整體響應(yīng)時間疫向。

- <font color='red'>新的資源分配手段</font>

? 對于多應(yīng)用共享同一數(shù)據(jù)庫的系統(tǒng)而言,可在應(yīng)用層通過數(shù)據(jù)庫連接的配置豪嚎,實現(xiàn)數(shù)據(jù)庫連接池技術(shù)搔驼,幾年錢也許還是個新鮮話題,對于目前的業(yè)務(wù)系統(tǒng)而言侈询,如果設(shè)計中還沒有考慮到連接池的應(yīng)用舌涨。某一應(yīng)用最大可用數(shù)據(jù)庫連接數(shù)的限制,避免某一應(yīng)用獨占所有數(shù)據(jù)庫資源扔字。

- <font color='red'>統(tǒng)一的連接管理囊嘉,避免數(shù)據(jù)庫連接泄漏</font>

? 在較為完備的數(shù)據(jù)庫連接池實現(xiàn)中温技,可根據(jù)預先的連接占用超時設(shè)定,強制收回被占用連接扭粱。從而避免了常規(guī)數(shù)據(jù)庫連接操作中可能出現(xiàn)的資源泄漏舵鳞。

### 數(shù)據(jù)庫連接池的工作原理

分位3步:

- 連接池的建立

- 連接池中連接的使用管理

- 連接池的關(guān)閉

<font color='red'>連接池的建立。</font>一般在系統(tǒng)初始化時琢蛤,連接池會根據(jù)系統(tǒng)配置建立蜓堕,并在池中創(chuàng)建了幾個連接對象,以便使用時能從連接池中獲取博其。<font color='cornflowerblue'>連接池中的連接不能隨意創(chuàng)建和關(guān)閉</font>套才,這樣避免了連接隨意建立和關(guān)閉造成的系統(tǒng)開銷。

<font color='red'>連接池的管理慕淡。</font>連接池管理策略是連接池機制的核心背伴,連接池內(nèi)連接的分配和釋放對系統(tǒng)的性能有很大的影響。其管理策略是:

```oop

當客戶請求數(shù)據(jù)庫連接時儡率,首先查看連接池中是否有空閑連接挂据,如果存在空閑連接,則將連接分配給客戶使用儿普;如果沒有空閑連接崎逃,則查看當前所開的連接數(shù)是否已經(jīng)達到最大連接數(shù),如果沒達到就重新創(chuàng)建一個連接給請求的客戶眉孩;如果達到就按設(shè)定的最大等待時間進行等待个绍,如果超出最大等待時間,則拋出異常給客戶浪汪。

當客戶釋放數(shù)據(jù)庫連接時巴柿,先判斷該連接的引用次數(shù)是否超過了規(guī)定值,如果超過就從連接池中刪除該連接死遭,否則保留為其他客戶服務(wù)广恢。

該策略保證了數(shù)據(jù)庫連接的有效復用,避免頻繁的建立呀潭、釋放連接所帶來的系統(tǒng)資源開銷钉迷。

```

<font color='red'>連接池的關(guān)閉。</font>當應(yīng)用程序退出時钠署,關(guān)閉連接池中所有的連接糠聪,釋放連接池相關(guān)的資源,以便連接可以返回池中重復利用谐鼎。我們可以通過<font color='orange'>Connection</font>對象的<font color='orange'>Close</font>或<font color='orange'>Dispose</font>方法

## 常用的連接池

| 數(shù)據(jù)庫連接池 | 最新版本? ? | 發(fā)布時間 |

| ------------ | ------------ | -------- |

| c3p0? ? ? ? | c3p0-0.9.5.2 | 2015? ? |

| dbcp? ? ? ? | 2.2.0? ? ? ? | 2017? ? |

| **druid**? ? | 0.11.0? ? ? | 2017? ? |

| **HikariCP** | 2.7.6? ? ? ? | 2018? ? |

#### C3P0

<font color='red'>C3P0</font>在很長一段時間內(nèi)舰蟆,它一直是Java領(lǐng)域內(nèi)數(shù)據(jù)庫連接池的代名詞,當年盛極一時的<font color='red'>Hibernate</font>都將其作為內(nèi)置的數(shù)據(jù)庫連接池,可以業(yè)內(nèi)對它的穩(wěn)定性還是認可的身害。<font color='orange'>C3P0功能簡單易用味悄,穩(wěn)定性好這是它的優(yōu)點,但是性能上的缺點卻讓它徹底被打入冷宮</font>题造。<font color='red'>C3P0的性能很差</font>傍菇,差到即便是同時代的產(chǎn)品相比它也是墊底的

#### DBCP

屬于Apache頂級項目Commons中的核心子項目(最早在Jakarta Commons里就有),在Apache的生態(tài)圈中的影響里十分廣泛,比如最為大家所熟知的Tomcat就在內(nèi)部集成了DBCP界赔,實現(xiàn)JPA規(guī)范的<font color='orange'>OpenJPA</font>,也是默認集成DBCP的牵触。但DBCP并不是獨立實現(xiàn)連接池功能的淮悼,它內(nèi)部依賴于Commons中的另一個子項目Pool,連接池最核心的“池”揽思,就是由Pool組件提供的袜腥,因為核心功能依賴于Pool,所以DBCP本身只能做小版本的更新钉汗,真正大版本的更迭則完全依托于pool羹令。

#### 性能無敵的<font color='red'>HikariCP</font>

- 字節(jié)碼精簡:優(yōu)化代碼,直到編譯后的字節(jié)碼最少损痰,這樣福侈,CPU緩存可以加載更多的程序代碼;

- 優(yōu)化代理和攔截器:減少代碼卢未,例如<font color='orange'>HikariCP</font>的Statement proxy只有100行代碼肪凛;

- 自定義數(shù)組類型(<font color='orange'>FastStatementList</font>)代替<font color='orange'>ArrayList</font>:避免每次get()調(diào)用都要進行range check,避免調(diào)用remove()時的從頭到尾的掃描辽社;

- 自定義集合類型(<font color='orange'>ConcurrentBag</font>):提高并發(fā)讀寫的效率伟墙;

- 其他缺陷的優(yōu)化,比如對于耗時超過一個CPU時間片的方法調(diào)用的研究(但沒說具體怎么優(yōu)化)滴铅。

java代碼

```Java

@Test

? ? //Hikari

? ? public void test3() throws Exception{

? ? ? ? Properties properties = new Properties();

? ? ? ? properties.load(PoolTest.class.getClassLoader().getResourceAsStream("hikari.properties"));


? ? ? ? HikariConfig hikariConfig = new HikariConfig(properties);

? ? ? ? DataSource dataSource = new HikariDataSource(hikariConfig);

? ? ? ? System.out.println(dataSource.getConnection());

? ? }

```

properties配置文件

```properties

jdbcUrl=jdbc:mysql://127.0.0.1:3306/job?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai

username=root

password=root

driverClassName=com.mysql.cj.jdbc.Driver

```

#### 功能全面的<font color='red'>Druid</font>(德魯伊)

Druid 相對于其他數(shù)據(jù)庫連接池的優(yōu)點

- 強大的監(jiān)控特性戳葵,通過Druid提供的監(jiān)控功能,可以清楚知道連接池和SQL的工作情況汉匙。

- 監(jiān)控SQL的執(zhí)行時間拱烁、<font color='orange'>ResultSet</font>持有時間、返回行數(shù)盹兢、更新行數(shù)邻梆、錯誤次數(shù)、錯誤堆棧信息绎秒;

-? SQL執(zhí)行的耗時區(qū)間分布浦妄。什么是耗時區(qū)間分布呢?比如說,某個SQL執(zhí)行了1000次剂娄,其中0\~1毫秒?yún)^(qū)間50次蠢涝,1\~10毫秒800次,10\~100毫秒100次阅懦,100\~1000毫秒30次和二,1~10秒15次,10秒以上5次耳胎。通過耗時區(qū)間分布果善,能夠非常清楚知道SQL的執(zhí)行耗時情況;

-? 監(jiān)控連接池的物理連接創(chuàng)建和銷毀次數(shù)褒墨、邏輯連接的申請和關(guān)閉次數(shù)震贵、非空等待次數(shù)、<font color='orange'>PSCache</font>命中率等郁惜。

- 方便擴展堡距。Druid提供了Filter-Chain模式的擴展API,可以自己編寫Filter攔截JDBC中的任何方法兆蕉,可以在上面做任何事情羽戒,比如說性能監(jiān)控、SQL審計虎韵、用戶名密碼加密易稠、日志等等。

<font color='red'>Druid</font>集合了開源和商業(yè)數(shù)據(jù)庫連接池的優(yōu)秀特性劝术,并結(jié)合<font color='red'>阿里巴巴</font>大規(guī)乃醵啵苛刻生產(chǎn)環(huán)境的使用經(jīng)驗進行優(yōu)化。

| 配置? ? ? ? ? ? ? ? ? ? ? ? ? | 缺省值? ? ? ? ? ? | 說明? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? |

| ----------------------------- | ------------------ | ------------------------------------------------------------ |

| name? ? ? ? ? ? ? ? ? ? ? ? ? |? ? ? ? ? ? ? ? ? ? | 配置這個屬性的意義在于养晋,如果存在多個數(shù)據(jù)源衬吆,監(jiān)控的時候? 可以通過名字來區(qū)分開來。如果沒有配置绳泉,將會生成一個名字逊抡,? 格式是:"DataSource-" + System.identityHashCode(this) |

| jdbcUrl? ? ? ? ? ? ? ? ? ? ? |? ? ? ? ? ? ? ? ? ? | 連接數(shù)據(jù)庫的url,不同數(shù)據(jù)庫不一樣零酪。例如:? mysql : jdbc:mysql://10.20.153.104:3306/druid2? oracle : jdbc:oracle:thin:@10.20.149.85:1521:ocnauto |

| username? ? ? ? ? ? ? ? ? ? ? |? ? ? ? ? ? ? ? ? ? | 連接數(shù)據(jù)庫的用戶名? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? |

| password? ? ? ? ? ? ? ? ? ? ? |? ? ? ? ? ? ? ? ? ? | 連接數(shù)據(jù)庫的密碼冒嫡。如果你不希望密碼直接寫在配置文件中,? 可以使用ConfigFilter四苇。詳細看這里:? [https://github.com/alibaba/druid/wiki/%E4%BD%BF%E7%94%A8ConfigFilter](https://github.com/alibaba/druid/wiki/使用ConfigFilter) |

| driverClassName? ? ? ? ? ? ? | 根據(jù)url自動識別? ? | 這一項可配可不配孝凌,如果不配置druid會根據(jù)url自動識別dbType,然后選擇相應(yīng)的driverClassName |

| initialSize? ? ? ? ? ? ? ? ? | 0? ? ? ? ? ? ? ? ? | 初始化時建立物理連接的個數(shù)月腋。初始化發(fā)生在顯示調(diào)用init方法蟀架,或者第一次getConnection時 |

| maxActive? ? ? ? ? ? ? ? ? ? | 8? ? ? ? ? ? ? ? ? | 最大連接池數(shù)量? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? |

| maxIdle? ? ? ? ? ? ? ? ? ? ? | 8? ? ? ? ? ? ? ? ? | 已經(jīng)不再使用瓣赂,配置了也沒效果? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? |

| minIdle? ? ? ? ? ? ? ? ? ? ? |? ? ? ? ? ? ? ? ? ? | 最小連接池數(shù)量? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? |

| maxWait? ? ? ? ? ? ? ? ? ? ? |? ? ? ? ? ? ? ? ? ? | 獲取連接時最大等待時間,單位毫秒片拍。配置了maxWait之后煌集,? 缺省啟用公平鎖,并發(fā)效率會有所下降捌省,? 如果需要可以通過配置useUnfairLock屬性為true使用非公平鎖苫纤。 |

| poolPreparedStatements? ? ? ? | false? ? ? ? ? ? ? | 是否緩存preparedStatement,也就是PSCache纲缓。? PSCache對支持游標的數(shù)據(jù)庫性能提升巨大卷拘,比如說oracle。? 在mysql5.5以下的版本中沒有PSCache功能祝高,建議關(guān)閉掉恭金。 作者在5.5版本中使用PSCache,通過監(jiān)控界面發(fā)現(xiàn)PSCache有緩存命中率記錄褂策,? 該應(yīng)該是支持PSCache。 |

| maxOpenPreparedStatements? ? | -1? ? ? ? ? ? ? ? | 要啟用PSCache颓屑,必須配置大于0斤寂,當大于0時,? poolPreparedStatements自動觸發(fā)修改為true揪惦。? 在Druid中遍搞,不會存在Oracle下PSCache占用內(nèi)存過多的問題,? 可以把這個數(shù)值配置大一些器腋,比如說100 |

| validationQuery? ? ? ? ? ? ? |? ? ? ? ? ? ? ? ? ? | 用來檢測連接是否有效的sql溪猿,要求是一個查詢語句。? 如果validationQuery為null纫塌,testOnBorrow诊县、testOnReturn、? testWhileIdle都不會其作用措左。 |

| testOnBorrow? ? ? ? ? ? ? ? ? | true? ? ? ? ? ? ? | 申請連接時執(zhí)行validationQuery檢測連接是否有效依痊,做了這個配置會降低性能。 |

| testOnReturn? ? ? ? ? ? ? ? ? | false? ? ? ? ? ? ? | 歸還連接時執(zhí)行validationQuery檢測連接是否有效怎披,做了這個配置會降低性能 |

| testWhileIdle? ? ? ? ? ? ? ? | false? ? ? ? ? ? ? | 建議配置為true胸嘁,不影響性能,并且保證安全性凉逛。? 申請連接的時候檢測性宏,如果空閑時間大于? timeBetweenEvictionRunsMillis,? 執(zhí)行validationQuery檢測連接是否有效状飞。 |

| timeBetweenEvictionRunsMillis |? ? ? ? ? ? ? ? ? ? | 有兩個含義:? 1) Destroy線程會檢測連接的間隔時間? 2) testWhileIdle的判斷依據(jù)毫胜,詳細看testWhileIdle屬性的說明 |

| numTestsPerEvictionRun? ? ? ? |? ? ? ? ? ? ? ? ? ? | 不再使用书斜,一個DruidDataSource只支持一個EvictionRun? ? ? ? ? |

| minEvictableIdleTimeMillis? ? |? ? ? ? ? ? ? ? ? ? |? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? |

| connectionInitSqls? ? ? ? ? ? |? ? ? ? ? ? ? ? ? ? | 物理連接初始化的時候執(zhí)行的sql? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? |

| exceptionSorter? ? ? ? ? ? ? | 根據(jù)dbType自動識別 | 當數(shù)據(jù)庫拋出一些不可恢復的異常時,拋棄連接? ? ? ? ? ? ? ? ? |

| filters? ? ? ? ? ? ? ? ? ? ? |? ? ? ? ? ? ? ? ? ? | 屬性類型是字符串指蚁,通過別名的方式配置擴展插件菩佑,? 常用的插件有:? 監(jiān)控統(tǒng)計用的filter:stat? 日志用的filter:log4j? 防御sql注入的filter:wall |

| proxyFilters? ? ? ? ? ? ? ? ? |? ? ? ? ? ? ? ? ? ? | 類型是List<com.alibaba.druid.filter.Filter>,? 如果同時配置了filters和proxyFilters凝化,? 是組合關(guān)系稍坯,并非替換關(guān)系 |

Druid java代碼

```Java

public void test1() throws Exception{

? ? ? ? Properties properties = new Properties();

? ? ? ? properties.load(PoolTest.class.getClassLoader().getResourceAsStream("jdbc.properties"));

? ? ? ? DruidDataSource druidDataSource = new DruidDataSource();

? ? ? ? druidDataSource.configFromPropety(properties);

? ? ? ? Connection connection = druidDataSource.getConnection();

? ? ? ? System.out.println(connection);

? ? }

```

Druid properties配置文件

```properties

druid.url=jdbc:mysql://127.0.0.1:3306/job?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai

druid.username=root

druid.password=root

druid.driverClassName=com.mysql.cj.jdbc.Driver

```

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市搓劫,隨后出現(xiàn)的幾起案子瞧哟,更是在濱河造成了極大的恐慌,老刑警劉巖枪向,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件勤揩,死亡現(xiàn)場離奇詭異,居然都是意外死亡秘蛔,警方通過查閱死者的電腦和手機陨亡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來深员,“玉大人负蠕,你說我怎么就攤上這事【氤” “怎么了遮糖?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長叠赐。 經(jīng)常有香客問我欲账,道長,這世上最難降的妖魔是什么芭概? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任赛不,我火速辦了婚禮,結(jié)果婚禮上谈山,老公的妹妹穿的比我還像新娘俄删。我一直安慰自己,他們只是感情好奏路,可當我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布畴椰。 她就那樣靜靜地躺著,像睡著了一般鸽粉。 火紅的嫁衣襯著肌膚如雪斜脂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天触机,我揣著相機與錄音帚戳,去河邊找鬼玷或。 笑死,一個胖子當著我的面吹牛片任,可吹牛的內(nèi)容都是我干的偏友。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼对供,長吁一口氣:“原來是場噩夢啊……” “哼位他!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起产场,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤鹅髓,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后京景,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體窿冯,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年确徙,在試婚紗的時候發(fā)現(xiàn)自己被綠了醒串。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡鄙皇,死狀恐怖厦凤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情育苟,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布椎木,位于F島的核電站违柏,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏香椎。R本人自食惡果不足惜漱竖,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望畜伐。 院中可真熱鬧馍惹,春花似錦、人聲如沸玛界。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽慎框。三九已至良狈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間笨枯,已是汗流浹背薪丁。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工遇西, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人严嗜。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓粱檀,卻偏偏與公主長得像,于是被迫代替她去往敵國和親漫玄。 傳聞我的和親對象是個殘疾皇子茄蚯,可洞房花燭夜當晚...
    茶點故事閱讀 42,762評論 2 345