1、引言
1.1定義
數(shù)據(jù)庫連接是一種關(guān)鍵的有限的昂貴的資源杠园,這一點(diǎn)在多用戶的網(wǎng)頁應(yīng)用程序中體現(xiàn)得尤為突出。對(duì)數(shù)據(jù)庫連接的管理能顯著影響到整個(gè)應(yīng)用程序的伸縮性和健壯性,影響到程序的性能指標(biāo)野蝇。數(shù)據(jù)庫連接池正是針對(duì)這個(gè)問題提出來的。
數(shù)據(jù)庫連接池負(fù)責(zé)分配括儒、管理和釋放數(shù)據(jù)庫連接绕沈,它允許應(yīng)用程序重復(fù)使用一個(gè)現(xiàn)有的數(shù)據(jù)庫連接,而不是再重新建立一個(gè)帮寻;釋放空閑時(shí)間超過最大空閑時(shí)間的數(shù)據(jù)庫連接來避免因?yàn)闆]有釋放數(shù)據(jù)庫連接而引起的數(shù)據(jù)庫連接遺漏乍狐。這項(xiàng)技術(shù)能明顯提高對(duì)數(shù)據(jù)庫操作的性能。
2固逗、數(shù)據(jù)庫連接池:
2.1 原理
連接池基本的思想是在系統(tǒng)初始化的時(shí)候浅蚪,將數(shù)據(jù)庫連接作為對(duì)象存儲(chǔ)在內(nèi)存中藕帜,當(dāng)用戶需要訪問數(shù)據(jù)庫時(shí),并非建立一個(gè)新的連接惜傲,而是從連接池中取出一個(gè)已建立的空閑連接對(duì)象洽故。使用完畢后,用戶也并非將連接關(guān)閉操漠,而是將連接放回連接池中收津,以供下一個(gè)請(qǐng)求訪問使用。而連接的建立浊伙、斷開都由連接池自身來管理撞秋。同時(shí),還可以通過設(shè)置連接池的參數(shù)來控制連接池中的初始連接數(shù)嚣鄙、連接的上下限數(shù)以及每個(gè)連接的最大使用次數(shù)吻贿、最大空閑時(shí)間等等,也可以通過其自身的管理機(jī)制來監(jiān)視數(shù)據(jù)庫連接的數(shù)量哑子、使用情況等舅列。
2.2 常見數(shù)據(jù)庫連接池及其特點(diǎn)
在Java中開源的常用的數(shù)據(jù)庫連接池有以下幾種 :
1)DBCP
DBCP是一個(gè)依賴Jakarta commons-pool對(duì)象池機(jī)制的數(shù)據(jù)庫連接池.DBCP可以直接的在應(yīng)用程序中使用,Tomcat的數(shù)據(jù)源使用的就是DBCP卧蜓。
2)c3p0
c3p0是一個(gè)開放源代碼的JDBC連接池帐要,它在lib目錄中與Hibernate一起發(fā)布,包括了實(shí)現(xiàn)jdbc3和jdbc2擴(kuò)展規(guī)范說明的Connection 和Statement 池的DataSources 對(duì)象。
3)Druid
阿里出品弥奸,淘寶和支付寶專用數(shù)據(jù)庫連接池榨惠,但它不僅僅是一個(gè)數(shù)據(jù)庫連接池,它還包含一個(gè)ProxyDriver盛霎,一系列內(nèi)置的JDBC組件庫赠橙,一個(gè)SQL Parser。支持所有JDBC兼容的數(shù)據(jù)庫愤炸,包括Oracle期揪、MySql、Derby规个、Postgresql凤薛、SQL Server、H2等等绰姻。
Druid針對(duì)Oracle和MySql做了特別優(yōu)化枉侧,比如Oracle的PS Cache內(nèi)存占用優(yōu)化,MySql的ping檢測優(yōu)化狂芋。
Druid提供了MySql榨馁、Oracle、Postgresql帜矾、SQL-92的SQL的完整支持翼虫,這是一個(gè)手寫的高性能SQL Parser屑柔,支持Visitor模式,使得分析SQL的抽象語法樹很方便珍剑。
簡單SQL語句用時(shí)10微秒以內(nèi)掸宛,復(fù)雜SQL用時(shí)30微秒。
通過Druid提供的SQL Parser可以在JDBC層攔截SQL做相應(yīng)處理招拙,比如說分庫分表唧瘾、審計(jì)等。Druid防御SQL注入攻擊的WallFilter就是通過Druid的SQL Parser分析語義實(shí)現(xiàn)的别凤。
3. 主要配置說明
連接池配置大體可以分為基本配置饰序、關(guān)鍵配置、性能配置等主要配置规哪。
3.1 基本配置
基本配置是指連接池進(jìn)行數(shù)據(jù)庫連接的四個(gè)基本必需配置:
傳遞給JDBC驅(qū)動(dòng)的用于連接數(shù)據(jù)庫的用戶名求豫、密碼、URL以及驅(qū)動(dòng)類名诉稍。
基本配置 | DBCP | c3p0 | Druid |
---|---|---|---|
驅(qū)動(dòng)類名 | driverClassName | driverClass | driverClassName |
URL | url | jdbcUrl | url |
用戶名 | username | user | username |
密碼 | password | password | password |
注:在Druid連接池的配置中蝠嘉,driverClassName可配可不配,如果不配置會(huì)根據(jù)url自動(dòng)識(shí)別dbType(數(shù)據(jù)庫類型)杯巨,然后選擇相應(yīng)的driverClassName蚤告。
3.2 關(guān)鍵配置
為了發(fā)揮數(shù)據(jù)庫連接池的作用,在初始化時(shí)將創(chuàng)建一定數(shù)量的數(shù)據(jù)庫連接放到連接池中服爷,這些數(shù)據(jù)庫連接的數(shù)量是由最小數(shù)據(jù)庫連接數(shù)來設(shè)定的罩缴。無論這些數(shù)據(jù)庫連接是否被使用,連接池都將一直保證至少擁有這么多的連接數(shù)量层扶。連接池的最大數(shù)據(jù)庫連接數(shù)量限定了這個(gè)連接池能占有的最大連接數(shù),當(dāng)應(yīng)用程序向連接池請(qǐng)求的連接數(shù)超過最大連接數(shù)量時(shí)烙荷,這些請(qǐng)求將被加入到等待隊(duì)列中镜会。
最小連接數(shù):是數(shù)據(jù)庫一直保持的數(shù)據(jù)庫連接數(shù),所以如果應(yīng)用程序?qū)?shù)據(jù)庫連接的使用量不大终抽,將有大量的數(shù)據(jù)庫資源被浪費(fèi)戳表。
初始化連接數(shù):連接池啟動(dòng)時(shí)創(chuàng)建的初始化數(shù)據(jù)庫連接數(shù)量。
最大連接數(shù):是連接池能申請(qǐng)的最大連接數(shù)昼伴,如果數(shù)據(jù)庫連接請(qǐng)求超過此數(shù)匾旭,后面的數(shù)據(jù)庫連接請(qǐng)求被加入到等待隊(duì)列中。
最大等待時(shí)間:當(dāng)沒有可用連接時(shí)圃郊,連接池等待連接被歸還的最大時(shí)間价涝,超過時(shí)間則拋出異常,可設(shè)置參數(shù)為0或者負(fù)數(shù)使得無限等待(根據(jù)不同連接池配置)持舆。
關(guān)鍵配置 | DBCP | c3p0 | Druid |
---|---|---|---|
最小連接數(shù) | minIdle(0) | minPoolSize(3) | minIdle(0) |
初始化連接數(shù) | initialSize(0) | initialPoolSize(3) | initialSize(0) |
最大連接數(shù) | maxTotal(8) | maxPoolSize(15) | maxActive(8) |
最大等待時(shí)間 | maxWaitMillis(毫秒) | maxIdleTime(0秒) | maxWait(毫秒) |
注1:在DBCP連接池的配置中色瘩,還有一個(gè)maxIdle的屬性伪窖,表示最大空閑連接數(shù),超過的空閑連接將被釋放居兆,默認(rèn)值為8覆山。對(duì)應(yīng)的該屬性在Druid連接池已不再使用,配置了也沒有效果泥栖,c3p0連接池則沒有對(duì)應(yīng)的屬性簇宽。
注2:數(shù)據(jù)庫連接池在初始化的時(shí)候會(huì)創(chuàng)建initialSize個(gè)連接,當(dāng)有數(shù)據(jù)庫操作時(shí)吧享,會(huì)從池中取出一個(gè)連接魏割。如果當(dāng)前池中正在使用的連接數(shù)等于maxActive,則會(huì)等待一段時(shí)間耙蔑,等待其他操作釋放掉某一個(gè)連接见妒,如果這個(gè)等待時(shí)間超過了maxWait,則會(huì)報(bào)錯(cuò)甸陌;如果當(dāng)前正在使用的連接數(shù)沒有達(dá)到maxActive须揣,則判斷當(dāng)前是否空閑連接,如果有則直接使用空閑連接钱豁,如果沒有則新建立一個(gè)連接耻卡。在連接使用完畢后,不是將其物理連接關(guān)閉牲尺,而是將其放入池中等待其他操作復(fù)用卵酪。
3.3 性能配置
預(yù)緩存設(shè)置:即是PSCache,PSCache對(duì)支持游標(biāo)的數(shù)據(jù)庫性能提升巨大谤碳,比如說oracle溃卡。JDBC的標(biāo)準(zhǔn)參數(shù),用以控制數(shù)據(jù)源內(nèi)加載的PreparedStatements數(shù)量蜒简。但由于預(yù)緩存的statements屬于單個(gè)connection而不是整個(gè)連接池瘸羡,所以設(shè)置這個(gè)參數(shù)需要考慮到多方面的因素。
單個(gè)連接擁有的最大緩存數(shù):要啟用PSCache搓茬,必須配置大于0犹赖,當(dāng)大于0時(shí)跋选,poolPreparedStatements自動(dòng)觸發(fā)修改為true暴心。在Druid中,不會(huì)存在Oracle下PSCache占用內(nèi)存過多的問題钠糊,可以把這個(gè)數(shù)值配置大一些锡凝,比如說100
性能配置 | DBCP | c3p0 | Druid |
---|---|---|---|
開啟緩存功能 | poolPreparedStatements | maxStatements | poolPreparedStatements |
單個(gè)連接擁有的最大緩存數(shù) | maxOpenPrepared-Statements | maxStatementsPer-Connection | maxOpenPrepared-Statements |
連接有效性檢測設(shè)置:
連接池內(nèi)部有機(jī)制判斷粘昨,如果當(dāng)前的總的連接數(shù)少于miniIdle,則會(huì)建立新的空閑連接,以保證連接數(shù)得到miniIdle雾棺。如果當(dāng)前連接池中某個(gè)連接在空閑了timeBetweenEvictionRunsMillis時(shí)間后任然沒有使用膊夹,則被物理性的關(guān)閉掉。有些數(shù)據(jù)庫連接的時(shí)候有超時(shí)限制(mysql連接在8小時(shí)后斷開)捌浩,或者由于網(wǎng)絡(luò)中斷等原因放刨,連接池的連接會(huì)出現(xiàn)失效的情況,這時(shí)候設(shè)置一個(gè)testWhileIdle參數(shù)為true尸饺,可以保證連接池內(nèi)部定時(shí)檢測連接的可用性进统,不可用的連接會(huì)被拋棄或者重建,最大情況的保證從連接池中得到的Connection對(duì)象是可用的浪听。當(dāng)然螟碎,為了保證絕對(duì)的可用性,你也可以使用testOnBorrow為true(即在獲取Connection對(duì)象時(shí)檢測其可用性)迹栓,不過這樣會(huì)影響性能掉分。
有效性 | DBCP | c3p0 | Druid |
---|---|---|---|
申請(qǐng)連接檢測 | testOnBorrow | testConnectionOnCheckin | testOnBorrow |
是否超時(shí)檢測 | testWhileIdle | null | testWhileIdle |
空閑時(shí)間 | timeBetweenEvictionRunsMillis | idleConnectionTestPeriod | timeBetweenEvictionRunsMillis |
校驗(yàn)用sql語句 | validationQuery | preferredTestQuery | validationQuery |
歸還連接檢測 | testOnReturn | testConnectionOnCheckout | testOnReturn |