問(wèn)題一:什么是數(shù)據(jù)庫(kù)連接池,有什么作用? 數(shù)據(jù)庫(kù)連接是一種有限的昂貴的資源,
創(chuàng)新互聯(lián)公司擁有一支富有激情的企業(yè)網(wǎng)站制作團(tuán)隊(duì),在互聯(lián)網(wǎng)網(wǎng)站建設(shè)行業(yè)深耕十多年,專(zhuān)業(yè)且經(jīng)驗(yàn)豐富。十多年網(wǎng)站優(yōu)化營(yíng)銷(xiāo)經(jīng)驗(yàn),我們已為超過(guò)千家中小企業(yè)提供了成都網(wǎng)站建設(shè)、網(wǎng)站制作解決方案,按需網(wǎng)站建設(shè),設(shè)計(jì)滿(mǎn)意,售后服務(wù)無(wú)憂(yōu)。所有客戶(hù)皆提供一年免費(fèi)網(wǎng)站維護(hù)!
數(shù)據(jù)庫(kù)連接影響到程序的性能指標(biāo)。
數(shù)據(jù)庫(kù)連接池正是針對(duì)這個(gè)問(wèn)題提出來(lái)的。數(shù)據(jù)庫(kù)連接池負(fù)責(zé)分配、
管理和釋放數(shù)據(jù)庫(kù)連接,
它允許應(yīng)用程序重復(fù)使用一個(gè)現(xiàn)有的數(shù)據(jù)庫(kù)連接,
而再不是重新建立一個(gè);
釋放空閑時(shí)間超過(guò)最大空閑時(shí)間的數(shù)據(jù)庫(kù)連接來(lái)避免因?yàn)闆](méi)有釋放數(shù)
據(jù)庫(kù)連接而引起的數(shù)據(jù)庫(kù)連接遺漏。
這項(xiàng)技術(shù)能明顯提高對(duì)數(shù)據(jù)庫(kù)操作的性能。
問(wèn)題二:什么是數(shù)據(jù)庫(kù)連接池?謝謝了 數(shù)據(jù)庫(kù)連接池,簡(jiǎn)稱(chēng)dbcp databa績(jī)e connection pool
存在意義:
數(shù)據(jù)庫(kù)的連接是非常耗費(fèi)系統(tǒng)資源的,一個(gè)應(yīng)用通常都是需要與數(shù)據(jù)庫(kù)打交道,也就需要經(jīng)常連接數(shù)據(jù)庫(kù),這樣導(dǎo)致浪費(fèi)大量系統(tǒng)資源;
連接池的原理就是:我事先創(chuàng)建好幾個(gè)數(shù)據(jù)庫(kù)連接放著,當(dāng)我的系統(tǒng)需要操作數(shù)據(jù)庫(kù)時(shí)就從連接池里直接拿連接,并將這個(gè)連接標(biāo)記為 忙 ;用完后在放會(huì)池中,標(biāo)記為 空閑;;;
當(dāng)連接池里的連接都在被使用,如果此時(shí)還要連接,連接池就會(huì)在創(chuàng)建連接放到池里,,這些連接的數(shù)量,都是在配置文件里由你控制的
問(wèn)題三:數(shù)據(jù)庫(kù)連接池是什么意思? 像打開(kāi)關(guān)閉數(shù)據(jù)庫(kù)連接這種和數(shù)據(jù)庫(kù)的交互可能是很費(fèi)時(shí)的,尤其是當(dāng)客戶(hù)端數(shù)量增加的時(shí)候,會(huì)消耗大量的資源,成本是非常高的??梢栽趹?yīng)用服務(wù)器啟動(dòng)的時(shí)候建立很多個(gè)數(shù)據(jù)庫(kù)連接并維護(hù)在一個(gè)池中。連接請(qǐng)求由池中的連接提供。在連接使用完畢以后,把連接歸還到池中,以用于滿(mǎn)足將來(lái)更多的請(qǐng)求。
問(wèn)題四:數(shù)據(jù)庫(kù)連接池的工作機(jī)制是什么? 為什么要使用數(shù)據(jù)庫(kù)連接池?
答:
由于創(chuàng)建連接的代價(jià)是很高的, 我們每次訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)都重新創(chuàng)建連接的話(huà)是非常消耗性的.
我們可以再程序啟動(dòng)的時(shí)候先創(chuàng)建出一些連接, 放在一個(gè) *** 中, 訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)的時(shí)候從 *** 中獲取, 使用結(jié)束再放回 *** 中.
這樣做只是在程序啟動(dòng)的時(shí)候消耗性能去創(chuàng)建連接, 每次訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)的時(shí)候都是從內(nèi)存中獲取連接, 可以大大提升效率.
注意事項(xiàng):
由于池中增刪非常頻繁, 使用 *** LinkedList效率較高
*** 中所有連接都被占用時(shí)創(chuàng)建新連接, 但需要注意連接總數(shù)
使用組合模式/動(dòng)態(tài)代理處理釋放連接的方法, 當(dāng)運(yùn)行close方法時(shí), 將連接放回池中
關(guān)于數(shù)據(jù)庫(kù)連接池:
數(shù)據(jù)庫(kù)連接是一種關(guān)鍵的有限的昂貴的資源,這一點(diǎn)在多用戶(hù)的網(wǎng)頁(yè)應(yīng)用程序中體現(xiàn)得尤為突出。對(duì)數(shù)據(jù)庫(kù)連接的管理能顯著影響到整個(gè)應(yīng)用程序的伸縮性和健壯性,影響到程序的性能指標(biāo)。數(shù)據(jù)庫(kù)連接池正是針對(duì)這個(gè)問(wèn)題提出來(lái)的。
數(shù)據(jù)庫(kù)連接池負(fù)責(zé)分配、管理和釋放數(shù)據(jù)庫(kù)連接,它允許應(yīng)用程序重復(fù)使用一個(gè)現(xiàn)有的數(shù)據(jù)庫(kù)連接,而再不是重新建立一個(gè);釋放空閑時(shí)間超過(guò)最大空閑時(shí)間的數(shù)據(jù)庫(kù)連接來(lái)避免因?yàn)闆](méi)有釋放數(shù)據(jù)庫(kù)連接而引起的數(shù)據(jù)庫(kù)連接遺漏。這項(xiàng)技術(shù)能明顯提高對(duì)數(shù)據(jù)庫(kù)操作的性能。
數(shù)據(jù)庫(kù)連接池在初始化時(shí)將創(chuàng)建一定數(shù)量的數(shù)據(jù)庫(kù)連接放到連接池中,這些數(shù)據(jù)庫(kù)連接的數(shù)量是由最小數(shù)據(jù)庫(kù)連接數(shù)來(lái)設(shè)定的。無(wú)論這些數(shù)據(jù)庫(kù)連接是否被 使用,連接池都將一直保證至少擁有這么多的連接數(shù)量。連接池的最大數(shù)據(jù)庫(kù)連接數(shù)量限定了這個(gè)連接池能占有的最大連接數(shù),當(dāng)應(yīng)用程序向連接池請(qǐng)求的連接數(shù)超 過(guò)最大連接數(shù)量時(shí),這些請(qǐng)求將被加入到等待隊(duì)列中。
數(shù)據(jù)庫(kù)連接池的最小連接數(shù)和最大連接數(shù)的設(shè)置要考慮到下列幾個(gè)因素:
1) 最小連接數(shù)是連接池一直保持的數(shù)據(jù)庫(kù)連接,所以如果應(yīng)用程序?qū)?shù)據(jù)庫(kù)連接的使用量不大,將會(huì)有大量的數(shù)據(jù)庫(kù)連接資源被浪費(fèi);
2) 最大連接數(shù)是連接池能申請(qǐng)的最大連接數(shù),如果數(shù)據(jù)庫(kù)連接請(qǐng)求超過(guò)此數(shù),后面的數(shù)據(jù)庫(kù)連接請(qǐng)求將被加入到等待隊(duì)列中,這會(huì)影響之后的數(shù)據(jù)庫(kù)操作。
3) 如果最小連接數(shù)與最大連接數(shù)相差太大,那么最先的連接請(qǐng)求將會(huì)獲利,之后超過(guò)最小連接數(shù)量的連接請(qǐng)求等價(jià)于建立一個(gè)新的數(shù)據(jù)庫(kù)連接。不過(guò),這些大于最小連接數(shù)的數(shù)據(jù)庫(kù)連接在使用完不會(huì)馬上被釋放,它將被放到連接池中等待重復(fù)使用或是空閑超時(shí)后被釋放。
J2EE服務(wù)器啟動(dòng)時(shí)會(huì)建立一定數(shù)量的池連接,并一直維持不少于此數(shù)目的池連接。
調(diào)用:客戶(hù)端程序需要連接時(shí),池驅(qū)動(dòng)程序會(huì)返回一個(gè)未使用的池連接并將其表記為 忙。如果當(dāng)前沒(méi)有空閑連接,池驅(qū)動(dòng)程序就新建一定數(shù)量的連接,新建連接的數(shù)量有配置參數(shù)決定。
釋放:當(dāng)使用的池連接調(diào)用完成后,池驅(qū)動(dòng)程序?qū)⒋诉B接表記為空閑, 其他調(diào)用就可以使用這個(gè)連接
問(wèn)題五:數(shù)據(jù)庫(kù)連接池的作用是什么? 連接池是被j2ee服務(wù)器打開(kāi)和維護(hù)的 對(duì)應(yīng)1、2、4的JDBC驅(qū)動(dòng)程序 連接池一般比直接連接更有優(yōu)越性 因?yàn)樗岣吡诵阅艿耐瑫r(shí)還保存了 寶貴的資源。 打開(kāi)數(shù)據(jù)庫(kù)連接時(shí)CPU和網(wǎng)絡(luò)的重要 任務(wù),因此,在整個(gè)應(yīng)用程序的使用過(guò)程 當(dāng)中重復(fù)的打開(kāi)直接連接將導(dǎo)致性能的下降。 而池連接只在服務(wù)器啟動(dòng)時(shí)打開(kāi)一次,從而 消除了這種性能問(wèn)題。 另外,因?yàn)檫B接只用于很短的時(shí)間, 所以,連接可以被有效共享, 而且有關(guān)連接參數(shù)的特有信息, 只對(duì)池驅(qū)動(dòng)程序有效, 如數(shù)據(jù)庫(kù)用戶(hù)名稱(chēng)和密碼, 從而增強(qiáng)了系統(tǒng)的安全性和可管理性。
問(wèn)題六:數(shù)據(jù)庫(kù)連接池的工作機(jī)制是什么 連接池的實(shí)現(xiàn)是以空間換時(shí)間。
J2EE服務(wù)器啟動(dòng)時(shí)會(huì)建立一定數(shù)量的池連接,并一直維持不少于此數(shù)目的池連接??蛻?hù)端程序需要連接時(shí),池驅(qū)動(dòng)程序會(huì)返回一個(gè)未使用的池連接并將其表記為忙。如果當(dāng)前沒(méi)有空閑連接,池驅(qū)動(dòng)程序就新建一定數(shù)量的連接,新建連接的數(shù)量有配置參數(shù)決定。當(dāng)使用的池連接調(diào)用完成后,池驅(qū)動(dòng)程序?qū)⒋诉B接表記為空閑,其他調(diào)用就可以使用這個(gè)連接。
問(wèn)題七:數(shù)據(jù)庫(kù)連接池的作用是什么? 連接池是被j2ee服務(wù)器打開(kāi)和維護(hù)的
對(duì)應(yīng)1、2、4的JDBC驅(qū)動(dòng)程序
連接池一般比直接連接更有優(yōu)越性
因?yàn)樗岣吡诵阅艿耐瑫r(shí)還保存了
寶貴的資源。
打開(kāi)數(shù)據(jù)庫(kù)連接時(shí)CPU和網(wǎng)絡(luò)的重要
任務(wù),因此,在整個(gè)應(yīng)用程序的使用過(guò)程
當(dāng)中重復(fù)的打開(kāi)直接連接將導(dǎo)致性能的下降。
而池連接只在服務(wù)器啟動(dòng)時(shí)打開(kāi)一次,從而
消除了這種性能問(wèn)題。
另外,因?yàn)檫B接只用于很短的時(shí)間,
所以,連接可以被有效共享,
而且有關(guān)連接參數(shù)的特有信息,
只對(duì)池驅(qū)動(dòng)程序有效,
如數(shù)據(jù)庫(kù)用戶(hù)名稱(chēng)和密碼,
從而增強(qiáng)了系統(tǒng)的安全性和可管理性。
問(wèn)題八:開(kāi)源的數(shù)據(jù)庫(kù)連接池和普通的數(shù)據(jù)庫(kù)連接池有什么區(qū)別 在項(xiàng)目中嘗試使用了幾種開(kāi)源的數(shù)據(jù)庫(kù)連接池實(shí)現(xiàn)。一種是dbcp,一種是c3p0,還有一種是proxool,這幾種數(shù)據(jù)庫(kù)連接池都可以很容易的在Spring配置起來(lái)。性能總體上上感覺(jué)dbcp為最優(yōu),因?yàn)榉€(wěn)定性和并發(fā)性都是我的項(xiàng)目需要的。
項(xiàng)目中經(jīng)過(guò)反復(fù)測(cè)試,如果web server和數(shù)據(jù)庫(kù)server不是同一個(gè)機(jī)器的話(huà),在斷網(wǎng)時(shí)間比較短的時(shí)間內(nèi)三種數(shù)據(jù)庫(kù)連接池都能較好的重連,但是在斷網(wǎng)時(shí)間超過(guò)8個(gè)鐘頭 proxool就不能恢復(fù)工作了。但是dbcp卻能很快的重新連接。實(shí)際生產(chǎn)環(huán)境中穩(wěn)定性和總體性能是最重要的,都需要做相應(yīng)的測(cè)試才能放心的讓系統(tǒng)上生產(chǎn)線(xiàn)。
這里給出項(xiàng)目中數(shù)據(jù)庫(kù)連接池配置:
dbcp的jndi:13 4 java:p/env/jdbc/mysql5 6 proxool(proxool-0.9.0RC1)的配置: .mysql.jdbc.Driver jdbc:mysql:ip:3306/dbname?useUnicode=truecharacterEncoding=utf8autoReconnect=true user password 500 15000 select CURRENT_DATE true mysqlProxoolDataSource 1000 false 建議使用DBCP,配置在tomcat中,然后在spring中使用jndi的形式獲取。 c3p0(c3p0-0.9.0): 1 3 4 .mysql.jdbc.Driver 5 6 7 jdbc:mysql:192.168.0.225:3306/sendinmdb?useUnicode=truecharacterEncoding=utf8autoReconnect=true 8 9 10 ********11 12 13 ********14 15 16 10017 18 19 5020 21 22 10023 24 25 100026 27 28 3029 30 直接copy paste到spring配置文件里就可以使用了。 配置一些額外的tomcat 的DBCP連接池參數(shù),也可以更好的使用到類(lèi)似proxool提供的功能,只是dbcp更加穩(wěn)定而已。tomcat/conf/context.xml中插入一個(gè)Resource元素: 解釋一下以下這些參數(shù)的含義:
validationQuery = select current_date()
testOnBorrow = true
testOnReturn = false
testWhileIdle = true
當(dāng) 從池中獲取一個(gè)Connection后使用 select current_date() 來(lái)測(cè)試該數(shù)據(jù)庫(kù)連接的可用性,如果SQL語(yǔ)句返回結(jié)果則認(rèn)為是一個(gè)有效的連接,否則將繼續(xù)測(cè)試知道可以拿到有效的連接。當(dāng)返回Connection給池的時(shí)候不進(jìn)行驗(yàn)證,但是Connection空閑的時(shí)候就要進(jìn)行認(rèn)證。
timeBetweenEvictionRunsMillis = 15000
DBCP 清空線(xiàn)程睡眠的間隙,如值為負(fù)數(shù)則不運(yùn)行該線(xiàn)程
numTestsPerEvictionRun = 10"......
問(wèn)題九:sqlite 使用什么數(shù)據(jù)庫(kù)連接池 數(shù)據(jù)庫(kù)連接是一種有限的昂貴的資源,
數(shù)據(jù)庫(kù)連接影響到程序的性能指標(biāo)。
數(shù)據(jù)庫(kù)連接池正是針對(duì)這個(gè)問(wèn)題提出來(lái)的。數(shù)據(jù)庫(kù)連接池負(fù)責(zé)分配、
管理和釋放數(shù)據(jù)庫(kù)連接,
它允許應(yīng)用程序重復(fù)使用一個(gè)現(xiàn)有的數(shù)據(jù)庫(kù)連接,
而再不是重新建立一個(gè);
釋放空閑時(shí)間超過(guò)最大空閑時(shí)間的數(shù)據(jù)庫(kù)連接來(lái)避免因?yàn)闆](méi)有釋放數(shù)
據(jù)庫(kù)連接而引起的數(shù)據(jù)庫(kù)連接遺漏。
這項(xiàng)技術(shù)能明顯提高對(duì)數(shù)據(jù)庫(kù)操作的性能。
問(wèn)題十:說(shuō)出數(shù)據(jù)連接池的工作機(jī)制是什么? 以典型的數(shù)據(jù)庫(kù)連接池為例:首先普通的數(shù)據(jù)庫(kù)訪(fǎng)問(wèn)是這樣的:程序和數(shù)據(jù)庫(kù)建立連接,發(fā)送數(shù)據(jù)操作的指令,完成后斷開(kāi)連接。等下一次請(qǐng)求的時(shí)候重復(fù)這個(gè)過(guò)程,即每個(gè)請(qǐng)求都需要和數(shù)據(jù)庫(kù)建立連接和斷開(kāi)連接,這樣當(dāng)數(shù)據(jù)量大的時(shí)候系統(tǒng)的消耗是很大的。連接池就是為了解決這個(gè)問(wèn)題:在一個(gè)空間中預(yù)先建立好一定數(shù)量的連接,當(dāng)程序請(qǐng)求數(shù)據(jù)時(shí)直接使用池中的現(xiàn)存的連接,不需要重復(fù)建立連接和斷開(kāi)的過(guò)程,節(jié)省了時(shí)間提高了性能
數(shù)據(jù)庫(kù)連接池的基本原理是在內(nèi)部對(duì)象池中維護(hù)一定數(shù)量的數(shù)據(jù)庫(kù)連接,并對(duì)外暴露數(shù)據(jù)庫(kù)連接獲取和返回方法。如:
外部使用者可通過(guò)getConnection 方法獲取連接,使用完畢后再通過(guò)releaseConnection 方法將連接返回,注意此時(shí)連接并沒(méi)有關(guān)閉,而是由連接池管理器回收,并為下一次使用做好準(zhǔn)備。
這次我們采取技術(shù)演進(jìn)的方式來(lái)談?wù)剶?shù)據(jù)庫(kù)連接池的技術(shù)出現(xiàn)過(guò)程及其原理,以及當(dāng)下最流行的開(kāi)源數(shù)據(jù)庫(kù)連接池jar包。
1、原理
一般來(lái)說(shuō),Java應(yīng)用程序訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)的過(guò)程是 :
①裝載數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序;
②通過(guò)jdbc建立數(shù)據(jù)庫(kù)連接;
③訪(fǎng)問(wèn)數(shù)據(jù)庫(kù),執(zhí)行sql語(yǔ)句;
④斷開(kāi)數(shù)據(jù)庫(kù)連接。
2、代碼
3、分析
程序開(kāi)發(fā)過(guò)程中,存在很多問(wèn)題:首先,每一次web請(qǐng)求都要建立一次數(shù)據(jù)庫(kù)連接。建立連接是一個(gè)費(fèi)時(shí)的活動(dòng),每次都得花費(fèi)0.05s~1s的時(shí)間,而且系統(tǒng)還要分配內(nèi)存資源。這個(gè)時(shí)間對(duì)于一次或幾次數(shù)據(jù)庫(kù)操作,或許感覺(jué)不出系統(tǒng)有多大的開(kāi)銷(xiāo)??墒菍?duì)于現(xiàn)在的web應(yīng)用,尤其是大型電子商務(wù)網(wǎng)站,同時(shí)有幾百人甚至幾千人在線(xiàn)是很正常的事。在這種情況下,頻繁的進(jìn)行數(shù)據(jù)庫(kù)連接操作勢(shì)必占用很多的系統(tǒng)資源,網(wǎng)站的響應(yīng)速度必定下降,嚴(yán)重的甚至?xí)斐煞?wù)器的崩潰。不是危言聳聽(tīng),這就是制約某些電子商務(wù)網(wǎng)站發(fā)展的技術(shù)瓶頸問(wèn)題。其次,對(duì)于每一次數(shù)據(jù)庫(kù)連接,使用完后都得斷開(kāi)。否則,如果程序出現(xiàn)異常而未能關(guān)閉,將會(huì)導(dǎo)致數(shù)據(jù)庫(kù)系統(tǒng)中的內(nèi)存泄漏,最終將不得不重啟數(shù)據(jù)庫(kù)。還有,這種開(kāi)發(fā)不能控制被創(chuàng)建的連接對(duì)象數(shù),系統(tǒng)資源會(huì)被毫無(wú)顧及的分配出去,如連接過(guò)多,也可能導(dǎo)致內(nèi)存泄漏,服務(wù)器崩潰。
上述的用戶(hù)查詢(xún)案例,如果同時(shí)有1000人訪(fǎng)問(wèn),就會(huì)不斷的有數(shù)據(jù)庫(kù)連接、斷開(kāi)操作:
通過(guò)上面的分析,我們可以看出來(lái),“數(shù)據(jù)庫(kù)連接”是一種稀缺的資源,為了保障網(wǎng)站的正常使用,應(yīng)該對(duì)其進(jìn)行妥善管理。其實(shí)我們查詢(xún)完數(shù)據(jù)庫(kù)后,如果不關(guān)閉連接,而是暫時(shí)存放起來(lái),當(dāng)別人使用時(shí),把這個(gè)連接給他們使用。就避免了一次建立數(shù)據(jù)庫(kù)連接和斷開(kāi)的操作時(shí)間消耗。原理如下:
由上面的分析可以看出,問(wèn)題的根源就在于對(duì)數(shù)據(jù)庫(kù)連接資源的低效管理。我們知道,對(duì)于共享資源,有一個(gè)很著名的設(shè)計(jì)模式:資源池(resource pool)。該模式正是為了解決資源的頻繁分配﹑釋放所造成的問(wèn)題。為解決上述問(wèn)題,可以采用數(shù)據(jù)庫(kù)連接池技術(shù)。數(shù)據(jù)庫(kù)連接池的基本思想就是為數(shù)據(jù)庫(kù)連接建立一個(gè)“緩沖池”。預(yù)先在緩沖池中放入一定數(shù)量的連接,當(dāng)需要建立數(shù)據(jù)庫(kù)連接時(shí),只需從“緩沖池”中取出一個(gè),使用完畢之后再放回去。我們可以通過(guò)設(shè)定連接池最大連接數(shù)來(lái)防止系統(tǒng)無(wú)盡的與數(shù)據(jù)庫(kù)連接。更為重要的是我們可以通過(guò)連接池的管理機(jī)制監(jiān)視數(shù)據(jù)庫(kù)的連接的數(shù)量﹑使用情況,為系統(tǒng)開(kāi)發(fā)﹑測(cè)試及性能調(diào)整提供依據(jù)。
我們自己嘗試開(kāi)發(fā)一個(gè)連接池,來(lái)為上面的查詢(xún)業(yè)務(wù)提供數(shù)據(jù)庫(kù)連接服務(wù):
① 編寫(xiě)class 實(shí)現(xiàn)DataSource 接口
② 在class構(gòu)造器一次性創(chuàng)建10個(gè)連接,將連接保存LinkedList中
③ 實(shí)現(xiàn)getConnection 從 LinkedList中返回一個(gè)連接
④ 提供將連接放回連接池中方法
1、連接池代碼
2、使用連接池重構(gòu)我們的用戶(hù)查詢(xún)函數(shù)
這就是數(shù)據(jù)庫(kù)連接池的原理,它大大提供了數(shù)據(jù)庫(kù)連接的利用率,減小了內(nèi)存吞吐的開(kāi)銷(xiāo)。我們?cè)陂_(kāi)發(fā)過(guò)程中,就不需要再關(guān)心數(shù)據(jù)庫(kù)連接的問(wèn)題,自然有數(shù)據(jù)庫(kù)連接池幫助我們處理,這回放心了吧。但連接池需要考慮的問(wèn)題不僅僅如此,下面我們就看看還有哪些問(wèn)題需要考慮。
1、并發(fā)問(wèn)題
為了使連接管理服務(wù)具有最大的通用性,必須考慮多線(xiàn)程環(huán)境,即并發(fā)問(wèn)題。這個(gè)問(wèn)題相對(duì)比較好解決,因?yàn)閖ava語(yǔ)言自身提供了對(duì)并發(fā)管理的支持,使用synchronized關(guān)鍵字即可確保線(xiàn)程是同步的。使用方法為直接在類(lèi)方法前面加上synchronized關(guān)鍵字,如:
2、多數(shù)據(jù)庫(kù)服務(wù)器和多用戶(hù)
對(duì)于大型的企業(yè)級(jí)應(yīng)用,常常需要同時(shí)連接不同的數(shù)據(jù)庫(kù)(如連接oracle和sybase)。如何連接不同的數(shù)據(jù)庫(kù)呢?我們采用的策略是:設(shè)計(jì)一個(gè)符合單例模式的連接池管理類(lèi),在連接池管理類(lèi)的唯一實(shí)例被創(chuàng)建時(shí)讀取一個(gè)資源文件,其中資源文件中存放著多個(gè)數(shù)據(jù)庫(kù)的url地址等信息。根據(jù)資源文件提供的信息,創(chuàng)建多個(gè)連接池類(lèi)的實(shí)例,每一個(gè)實(shí)例都是一個(gè)特定數(shù)據(jù)庫(kù)的連接池。連接池管理類(lèi)實(shí)例為每個(gè)連接池實(shí)例取一個(gè)名字,通過(guò)不同的名字來(lái)管理不同的連接池。
對(duì)于同一個(gè)數(shù)據(jù)庫(kù)有多個(gè)用戶(hù)使用不同的名稱(chēng)和密碼訪(fǎng)問(wèn)的情況,也可以通過(guò)資源文件處理,即在資源文件中設(shè)置多個(gè)具有相同url地址,但具有不同用戶(hù)名和密碼的數(shù)據(jù)庫(kù)連接信息。
3、事務(wù)處理
我們知道,事務(wù)具有原子性,此時(shí)要求對(duì)數(shù)據(jù)庫(kù)的操作符合“all-all-nothing”原則即對(duì)于一組sql語(yǔ)句要么全做,要么全不做。
在java語(yǔ)言中,connection類(lèi)本身提供了對(duì)事務(wù)的支持,可以通過(guò)設(shè)置connection的autocommit屬性為false 然后顯式的調(diào)用commit或rollback方法來(lái)實(shí)現(xiàn)。但要高效的進(jìn)行connection復(fù)用,就必須提供相應(yīng)的事務(wù)支持機(jī)制??刹捎妹恳粋€(gè)事務(wù)獨(dú)占一個(gè)連接來(lái)實(shí)現(xiàn),這種方法可以大大降低事務(wù)管理的復(fù)雜性。
4、連接池的分配與釋放
連接池的分配與釋放,對(duì)系統(tǒng)的性能有很大的影響。合理的分配與釋放,可以提高連接的復(fù)用度,從而降低建立新連接的開(kāi)銷(xiāo),同時(shí)還可以加快用戶(hù)的訪(fǎng)問(wèn)速度。
對(duì)于連接的管理可使用空閑池。即把已經(jīng)創(chuàng)建但尚未分配出去的連接按創(chuàng)建時(shí)間存放到一個(gè)空閑池中。每當(dāng)用戶(hù)請(qǐng)求一個(gè)連接時(shí),系統(tǒng)首先檢查空閑池內(nèi)有沒(méi)有空閑連接。如果有就把建立時(shí)間最長(zhǎng)(通過(guò)容器的順序存放實(shí)現(xiàn))的那個(gè)連接分配給他(實(shí)際是先做連接是否有效的判斷,如果可用就分配給用戶(hù),如不可用就把這個(gè)連接從空閑池刪掉,重新檢測(cè)空閑池是否還有連接);如果沒(méi)有則檢查當(dāng)前所開(kāi)連接池是否達(dá)到連接池所允許的最大連接數(shù)(maxconn)如果沒(méi)有達(dá)到,就新建一個(gè)連接,如果已經(jīng)達(dá)到,就等待一定的時(shí)間(timeout)。如果在等待的時(shí)間內(nèi)有連接被釋放出來(lái)就可以把這個(gè)連接分配給等待的用戶(hù),如果等待時(shí)間超過(guò)預(yù)定時(shí)間timeout 則返回空值(null)。系統(tǒng)對(duì)已經(jīng)分配出去正在使用的連接只做計(jì)數(shù),當(dāng)使用完后再返還給空閑池。對(duì)于空閑連接的狀態(tài),可開(kāi)辟專(zhuān)門(mén)的線(xiàn)程定時(shí)檢測(cè),這樣會(huì)花費(fèi)一定的系統(tǒng)開(kāi)銷(xiāo),但可以保證較快的響應(yīng)速度。也可采取不開(kāi)辟專(zhuān)門(mén)線(xiàn)程,只是在分配前檢測(cè)的方法。
5、連接池的配置與維護(hù)
連接池中到底應(yīng)該放置多少連接,才能使系統(tǒng)的性能最佳?系統(tǒng)可采取設(shè)置最小連接數(shù)(minconn)和最大連接數(shù)(maxconn)來(lái)控制連接池中的連接。最小連接數(shù)是系統(tǒng)啟動(dòng)時(shí)連接池所創(chuàng)建的連接數(shù)。如果創(chuàng)建過(guò)多,則系統(tǒng)啟動(dòng)就慢,但創(chuàng)建后系統(tǒng)的響應(yīng)速度會(huì)很快;如果創(chuàng)建過(guò)少,則系統(tǒng)啟動(dòng)的很快,響應(yīng)起來(lái)卻慢。這樣,可以在開(kāi)發(fā)時(shí),設(shè)置較小的最小連接數(shù),開(kāi)發(fā)起來(lái)會(huì)快,而在系統(tǒng)實(shí)際使用時(shí)設(shè)置較大的,因?yàn)檫@樣對(duì)訪(fǎng)問(wèn)客戶(hù)來(lái)說(shuō)速度會(huì)快些。最大連接數(shù)是連接池中允許連接的最大數(shù)目,具體設(shè)置多少,要看系統(tǒng)的訪(fǎng)問(wèn)量,可通過(guò)反復(fù)測(cè)試,找到最佳點(diǎn)。
如何確保連接池中的最小連接數(shù)呢?有動(dòng)態(tài)和靜態(tài)兩種策略。動(dòng)態(tài)即每隔一定時(shí)間就對(duì)連接池進(jìn)行檢測(cè),如果發(fā)現(xiàn)連接數(shù)量小于最小連接數(shù),則補(bǔ)充相應(yīng)數(shù)量的新連接以保證連接池的正常運(yùn)轉(zhuǎn)。靜態(tài)是發(fā)現(xiàn)空閑連接不夠時(shí)再去檢查。
理解了連接池的原理就可以了,沒(méi)有必要什么都從頭寫(xiě)一遍,那樣會(huì)花費(fèi)很多時(shí)間,并且性能及穩(wěn)定性也不一定滿(mǎn)足要求。事實(shí)上,已經(jīng)存在很多流行的性能優(yōu)良的第三方數(shù)據(jù)庫(kù)連接池jar包供我們使用。如:
其中c3p0已經(jīng)很久沒(méi)有更新了。DBCP更新速度很慢,基本處于不活躍狀態(tài),而Druid和HikariCP處于活躍狀態(tài)的更新中。
連接池運(yùn)作原理在實(shí)際應(yīng)用開(kāi)發(fā)中,特別是在WEB應(yīng)用系統(tǒng)中,如果JSP、Servlet或EJB使用JDBC直接訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)中的數(shù)據(jù),每一次數(shù)據(jù)訪(fǎng)問(wèn)請(qǐng)求都必須經(jīng)歷建立數(shù)據(jù)庫(kù)連接、打開(kāi)數(shù)據(jù)庫(kù)、存取數(shù)據(jù)和關(guān)閉數(shù)據(jù)庫(kù)連接等步驟,而連接并打開(kāi)數(shù)據(jù)庫(kù)是一件既消耗資源又費(fèi)時(shí)的工作,如果頻繁發(fā)生這種數(shù)據(jù)庫(kù)操作,系統(tǒng)的性能必然會(huì)急劇下降,甚至?xí)?dǎo)致系統(tǒng)崩潰。數(shù)據(jù)庫(kù)連接池技術(shù)是解決這個(gè)問(wèn)題最常用的方法,在許多應(yīng)用程序服務(wù)器(例如:Weblogic,WebSphere,JBoss)中,基本都提供了這項(xiàng)技術(shù),無(wú)需自己編程,但是,深入了解這項(xiàng)技術(shù)是非常必要的。數(shù)據(jù)庫(kù)連接池技術(shù)的思想非常簡(jiǎn)單,將數(shù)據(jù)庫(kù)連接作為對(duì)象存儲(chǔ)在一個(gè)Vector對(duì)象中,一旦數(shù)據(jù)庫(kù)連接建立后,不同的數(shù)據(jù)庫(kù)訪(fǎng)問(wèn)請(qǐng)求就可以共享這些連接,這樣,通過(guò)復(fù)用這些已經(jīng)建立的數(shù)據(jù)庫(kù)連接,可以克服上述缺點(diǎn),極大地節(jié)省系統(tǒng)資源和時(shí)間。數(shù)據(jù)庫(kù)連接池的主要操作如下:(1)建立數(shù)據(jù)庫(kù)連接池對(duì)象(服務(wù)器啟動(dòng))。(2)按照事先指定的參數(shù)創(chuàng)建初始數(shù)量的數(shù)據(jù)庫(kù)連接(即:空閑連接數(shù))。(3)對(duì)于一個(gè)數(shù)據(jù)庫(kù)訪(fǎng)問(wèn)請(qǐng)求,直接從連接池中得到一個(gè)連接。如果數(shù)據(jù)庫(kù)連接池對(duì)象中沒(méi)有空閑的連接,且連接數(shù)沒(méi)有達(dá)到最大(即:最大活躍連接數(shù)),創(chuàng)建一個(gè)新的數(shù)據(jù)庫(kù)連接。(4)存取數(shù)據(jù)庫(kù)。(5)關(guān)閉數(shù)據(jù)庫(kù),釋放所有數(shù)據(jù)庫(kù)連接(此時(shí)的關(guān)閉數(shù)據(jù)庫(kù)連接,并非真正關(guān)閉,而是將其放入空閑隊(duì)列中。如實(shí)際空閑連接數(shù)大于初始空閑連接數(shù)則釋放連接)。(6)釋放數(shù)據(jù)庫(kù)連接池對(duì)象(服務(wù)器停止、維護(hù)期間,釋放數(shù)據(jù)庫(kù)連接池對(duì)象,并釋放所有連接)。連接池的實(shí)現(xiàn)1、連接池模型 本文討論的連接池包括一個(gè)連接池類(lèi)(DBConnectionPool)和一個(gè)連接池管理類(lèi)(DBConnetionPoolManager)。連接池類(lèi)是對(duì)某一數(shù)據(jù)庫(kù)所有連接的“緩沖池”,主要實(shí)現(xiàn)以下功能:①?gòu)倪B接池獲取或創(chuàng)建可用連接;②使用完畢之后,把連接返還給連接池;③在系統(tǒng)關(guān)閉前,斷開(kāi)所有連接并釋放連接占用的系統(tǒng)資源;④還能夠處理無(wú)效連接(原來(lái)登記為可用的連接,由于某種原因不再可用,如超時(shí),通訊問(wèn)題),并能夠限制連接池中的連接總數(shù)不低于某個(gè)預(yù)定值和不超過(guò)某個(gè)預(yù)定值。 連接池管理類(lèi)是連接池類(lèi)的外覆類(lèi)(wrapper),符合單例模式,即系統(tǒng)中只能有一個(gè)連接池管理類(lèi)的實(shí)例。其主要用于對(duì)多個(gè)連接池對(duì)象的管理,具有以下功能:①裝載并注冊(cè)特定數(shù)據(jù)庫(kù)的JDBC驅(qū)動(dòng)程序;②根據(jù)屬性文件給定的信息,創(chuàng)建連接池對(duì)象;③為方便管理多個(gè)連接池對(duì)象,為每一個(gè)連接池對(duì)象取一個(gè)名字,實(shí)現(xiàn)連接池名字與其實(shí)例之間的映射;④跟蹤客戶(hù)使用連接情況,以便需要是關(guān)閉連接釋放資源。連接池管理類(lèi)的引入主要是為了方便對(duì)多個(gè)連接池的使用和管理,如系統(tǒng)需要連接不同的數(shù)據(jù)庫(kù),或連接相同的數(shù)據(jù)庫(kù)但由于安全性問(wèn)題,需要不同的用戶(hù)使用不同的名稱(chēng)和密碼。 2、連接池實(shí)現(xiàn) 下面給出連接池類(lèi)和連接池管理類(lèi)的主要屬性及所要實(shí)現(xiàn)的基本接口: public class DBConnectionPool implements TimerListener{ private int checkedOut;//已被分配出去的連接數(shù) private ArrayList freeConnections = new ArrayList();//容器,空閑池,根據(jù)//創(chuàng)建時(shí)間順序存放已創(chuàng)建但尚未分配出去的連接 private int minConn;//連接池里連接的最小數(shù)量 private int maxConn;//連接池里允許存在的最大連接數(shù) private String name;//為這個(gè)連接池取個(gè)名字,方便管理 private String password;//連接數(shù)據(jù)庫(kù)時(shí)需要的密碼 private String url;//所要?jiǎng)?chuàng)建連接的數(shù)據(jù)庫(kù)的地址 private String user;//連接數(shù)據(jù)庫(kù)時(shí)需要的用戶(hù)名 public Timer timer;//定時(shí)器 public DBConnectionPool(String name, String URL, String user, String password, int maxConn)//公開(kāi)的構(gòu)造函數(shù) public synchronized void freeConnection(Connection con) //使用完畢之后,//把連接返還給空閑池 public synchronized Connection getConnection(long timeout)//得到一個(gè)連接,//timeout是等待時(shí)間 public synchronized void release()//斷開(kāi)所有連接,釋放占用的系統(tǒng)資源 private Connection newConnection()//新建一個(gè)數(shù)據(jù)庫(kù)連接 public synchronized void TimerEvent() //定時(shí)器事件處理函數(shù) } public class DBConnectionManager { static private DBConnectionManager instance;//連接池管理類(lèi)的唯一實(shí)例 static private int clients;//客戶(hù)數(shù)量 private ArrayList drivers = new ArrayList();//容器,存放數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序 private HashMap pools = new HashMap ();//以name/value的形式存取連接池//對(duì)象的名字及連接池對(duì)象 static synchronized public DBConnectionManager getInstance()//如果唯一的//實(shí)例instance已經(jīng)創(chuàng)建,直接返回這個(gè)實(shí)例;否則,調(diào)用私有構(gòu)造函數(shù),創(chuàng)//建連接池管理類(lèi)的唯一實(shí)例 private DBConnectionManager()//私有構(gòu)造函數(shù),在其中調(diào)用初始化函數(shù)init() public void freeConnection(String name, Connection con)// 釋放一個(gè)連接,//name是一個(gè)連接池對(duì)象的名字 public Connection getConnection(String name)//從名字為name的連接池對(duì)象//中得到一個(gè)連接 public Connection getConnection(String name, long time)//從名字為name //的連接池對(duì)象中取得一個(gè)連接,time是等待時(shí)間 public synchronized void release()//釋放所有資源 private void createPools(Properties props)//根據(jù)屬性文件提供的信息,創(chuàng)建//一個(gè)或多個(gè)連接池 private void init()//初始化連接池管理類(lèi)的唯一實(shí)例,由私有構(gòu)造函數(shù)調(diào)用 private void loadDrivers(Properties props)//裝載數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序 } 3、連接池使用 上面所實(shí)現(xiàn)的連接池在程序開(kāi)發(fā)時(shí)如何應(yīng)用到系統(tǒng)中呢?下面以Servlet為例說(shuō)明連接池的使用。 Servlet的生命周期是:在開(kāi)始建立servlet時(shí),調(diào)用其初始化(init)方法。之后每個(gè)用戶(hù)請(qǐng)求都導(dǎo)致一個(gè)調(diào)用前面建立的實(shí)例的service方法的線(xiàn)程。最后,當(dāng)服務(wù)器決定卸載一個(gè)servlet時(shí),它首先調(diào)用該servlet的 destroy方法。 根據(jù)servlet的特點(diǎn),我們可以在初始化函數(shù)中生成連接池管理類(lèi)的唯一實(shí)例(其中包括創(chuàng)建一個(gè)或多個(gè)連接池)。如: public void init() throws ServletException { connMgr = DBConnectionManager.getInstance(); } 然后就可以在service方法中通過(guò)連接池名稱(chēng)使用連接池,執(zhí)行數(shù)據(jù)庫(kù)操作。最后在destroy方法中釋放占用的系統(tǒng)資源,如: public void destroy() { connMgr.release(); super.destroy(); } 結(jié)束語(yǔ)在使用JDBC進(jìn)行與數(shù)據(jù)庫(kù)有關(guān)的應(yīng)用開(kāi)發(fā)中,數(shù)據(jù)庫(kù)連接的管理是一個(gè)難點(diǎn)。很多時(shí)候,連接的混亂管理所造成的系統(tǒng)資源開(kāi)銷(xiāo)過(guò)大成為制約大型企業(yè)級(jí)應(yīng)用效率的瓶頸。對(duì)于眾多用戶(hù)訪(fǎng)問(wèn)的Web應(yīng)用,采用數(shù)據(jù)庫(kù)連接技術(shù)的系統(tǒng)在效率和穩(wěn)定性上比采用傳統(tǒng)的其他方式的系統(tǒng)要好很多。本文闡述了使用JDBC訪(fǎng)問(wèn)數(shù)據(jù)庫(kù)的技術(shù)?討論了基于連接池技術(shù)的數(shù)據(jù)庫(kù)連接管理的關(guān)鍵問(wèn)題并給出了一個(gè)實(shí)現(xiàn)模型。文章所給出的是連接池管理程序的一種基本模式,為提高系統(tǒng)的整體性能,在此基礎(chǔ)上還可以進(jìn)行很多有意義的擴(kuò)展。
現(xiàn)在使用PDO鏈接數(shù)據(jù)庫(kù)的較多
連接是通過(guò)創(chuàng)建 PDO 基類(lèi)的實(shí)例而建立的。不管使用哪種驅(qū)動(dòng)程序,都是用 PDO 類(lèi)名。構(gòu)造函數(shù)接收用于指定數(shù)據(jù)庫(kù)源(所謂的 DSN)以及可能還包括用戶(hù)名和密碼(如果有的話(huà))的參數(shù)。
連接到 MySQL
?php
$dbh?=?new?PDO('mysql:host=localhost;dbname=test',?$user,?$pass);
?
如果有任何連接錯(cuò)誤,將拋出一個(gè) PDOException 異常對(duì)象。如果想處理錯(cuò)誤狀態(tài),可以捕獲異常,或者選擇留給通過(guò) set_exception_handler() 設(shè)置的應(yīng)用程序全局異常處理程序。
處理連接錯(cuò)誤
?php
try?{
$dbh?=?new?PDO('mysql:host=localhost;dbname=test',?$user,?$pass);
foreach($dbh-query('SELECT?*?from?FOO')?as?$row)?{
print_r($row);
}
$dbh?=?null;
}?catch?(PDOException?$e)?{
print?"Error!:?"?.?$e-getMessage()?.?"br/";
die();
}
?
如果應(yīng)用程序不在 PDO 構(gòu)造函數(shù)中捕獲異常,zend 引擎采取的默認(rèn)動(dòng)作是結(jié)束腳本并顯示一個(gè)回溯跟蹤,此回溯跟蹤可能泄漏完整的數(shù)據(jù)庫(kù)連接細(xì)節(jié),包括用戶(hù)名和密碼。因此有責(zé)任去顯式(通過(guò) catch 語(yǔ)句)或隱式(通過(guò) set_exception_handler() )地捕獲異常。
連接數(shù)據(jù)成功后,返回一個(gè) PDO 類(lèi)的實(shí)例給腳本,此連接在 PDO 對(duì)象的生存周期中保持活動(dòng)。要想關(guān)閉連接,需要銷(xiāo)毀對(duì)象以確保所有剩余到它的引用都被刪除,可以賦一個(gè) NULL 值給對(duì)象變量。如果不明確地這么做,PHP 在腳本結(jié)束時(shí)會(huì)自動(dòng)關(guān)閉連接。
關(guān)閉一個(gè)連接
?php
$dbh?=?new?PDO('mysql:host=localhost;dbname=test',?$user,?$pass);
//?在此使用連接
//?現(xiàn)在運(yùn)行完成,在此關(guān)閉連接
$dbh?=?null;
?
很多 web 應(yīng)用程序通過(guò)使用到數(shù)據(jù)庫(kù)服務(wù)的持久連接獲得好處。持久連接在腳本結(jié)束后不會(huì)被關(guān)閉,且被緩存,當(dāng)另一個(gè)使用相同憑證的腳本連接請(qǐng)求時(shí)被重用。持久連接緩存可以避免每次腳本需要與數(shù)據(jù)庫(kù)回話(huà)時(shí)建立一個(gè)新連接的開(kāi)銷(xiāo),從而讓 web 應(yīng)用程序更快。