一、為什么需要連接池
發(fā)展壯大離不開廣大客戶長(zhǎng)期以來的信賴與支持,我們將始終秉承“誠信為本、服務(wù)至上”的服務(wù)理念,堅(jiān)持“二合一”的優(yōu)良服務(wù)模式,真誠服務(wù)每家企業(yè),認(rèn)真做好每個(gè)細(xì)節(jié),不斷完善自我,成就企業(yè),實(shí)現(xiàn)共贏。行業(yè)涉及垃圾桶等,在成都網(wǎng)站建設(shè)、營銷型網(wǎng)站、WAP手機(jī)網(wǎng)站、VI設(shè)計(jì)、軟件開發(fā)等項(xiàng)目上具有豐富的設(shè)計(jì)經(jīng)驗(yàn)。
數(shù)據(jù)庫連接是一種關(guān)鍵的有限的昂貴的資源,這一點(diǎn)在多用戶的網(wǎng)頁應(yīng)用程序中體現(xiàn)得尤為突出。? 一個(gè)數(shù)據(jù)庫連接對(duì)象均對(duì)應(yīng)一個(gè)物理數(shù)據(jù)庫連接,每次操作都打開一個(gè)物理連接,使用完都關(guān)閉連接,這樣造成系統(tǒng)的 性能低下。
數(shù)據(jù)庫連接池的解決方案是在應(yīng)用程序啟動(dòng)時(shí)建立足夠的數(shù)據(jù)庫連接,并講這些連接組成一個(gè)連接池,由應(yīng)用程序動(dòng)態(tài)地對(duì)池中的連接進(jìn)行申請(qǐng)、使用和釋放。
對(duì)于多于連接池中連接數(shù)的并發(fā)請(qǐng)求,應(yīng)該在請(qǐng)求隊(duì)列中排隊(duì)等待。并且應(yīng)用程序可以根據(jù)池中連接的使用率,動(dòng)態(tài)增加或減少池中的連接數(shù)。
?連接池技術(shù)盡可能多地重用了消耗內(nèi)存地資源,大大節(jié)省了內(nèi)存,提高了服務(wù)器地服務(wù)效率,能夠支持更多的客戶服務(wù)。通過使用連接池,將大大提高程序運(yùn)行效率,同時(shí),我們可以通過其自身的管理機(jī)制來監(jiān)視數(shù)據(jù)庫連接的數(shù)量、使用情況等。
二、定義
數(shù)據(jù)庫連接池負(fù)責(zé)分配、管理和釋放數(shù)據(jù)庫連接,它允許應(yīng)用程序重復(fù)使用一個(gè)現(xiàn)有的數(shù)據(jù)庫連接,而不是再重新建立一個(gè)。
三、工作原理
連接池的工作原理主要由三部分組成,分別為連接池的建立、連接池中連接的使用管理、連接池的關(guān)閉。
第一、連接池的建立。一般在系統(tǒng)初始化時(shí),連接池會(huì)根據(jù)系統(tǒng)配置建立,并在池中創(chuàng)建了幾個(gè)連接對(duì)象,以便使用時(shí)能從連接池中獲取。連接池中的連接不能隨意創(chuàng)建和關(guān)閉,這樣避免了連接隨意建立和關(guān)閉造成的系統(tǒng)開銷。Java中提供了很多容器類可以方便的構(gòu)建連接池,例如Vector、Stack等。
第二、連接池的管理。連接池管理策略是連接池機(jī)制的核心,連接池內(nèi)連接的分配和釋放對(duì)系統(tǒng)的性能有很大的影響。其管理策略是: 當(dāng)客戶請(qǐng)求數(shù)據(jù)庫連接時(shí),首先查看連接池中是否有空閑連接,如果存在空閑連接,則將連接分配給客戶使用;如果沒有空閑連接,則查看當(dāng)前所開的連接數(shù)是否已經(jīng)達(dá)到最大連接數(shù),如果沒達(dá)到就重新創(chuàng)建一個(gè)連接給請(qǐng)求的客戶;如果達(dá)到就按設(shè)定的最大等待時(shí)間進(jìn)行等待,如果超出最大等待時(shí)間,則拋出異常給客戶。
當(dāng)客戶釋放數(shù)據(jù)庫連接時(shí),先判斷該連接的引用次數(shù)是否超過了規(guī)定值,如果超過就從連接池中刪除該連接,否則保留為其他客戶服務(wù)。
該策略保證了數(shù)據(jù)庫連接的有效復(fù)用,避免頻繁的建立、釋放連接所帶來的系統(tǒng)資源開銷。
?第三、連接池的關(guān)閉。當(dāng)應(yīng)用程序退出時(shí),關(guān)閉連接池中所有的連接,釋放連接池相關(guān)的資源,該過程正好與創(chuàng)建相反。
四、傳統(tǒng)數(shù)據(jù)庫連接對(duì)比數(shù)據(jù)庫連接池
不使用數(shù)據(jù)庫連接池的步驟:
TCP建立連接的三次握手
MySQL認(rèn)證的三次握手
真正的SQL執(zhí)行
MySQL的關(guān)閉
TCP的四次握手關(guān)閉
可以看到,為了執(zhí)行一條SQL,卻多了非常多我們不關(guān)心的網(wǎng)絡(luò)交互。優(yōu)點(diǎn):實(shí)現(xiàn)簡(jiǎn)單
缺點(diǎn):
- 網(wǎng)絡(luò)IO較多
- 數(shù)據(jù)庫的負(fù)載較高
- 響應(yīng)時(shí)間較長(zhǎng)及QPS較低
- 應(yīng)用頻繁的創(chuàng)建連接和關(guān)閉連接,導(dǎo)致臨時(shí)對(duì)象較多,GC頻繁
- 在關(guān)閉連接后,會(huì)出現(xiàn)大量TIME_WAIT 的TCP狀態(tài)(在2個(gè)MSL之后關(guān)閉)
使用數(shù)據(jù)庫連接池的步驟:
第一次訪問的時(shí)候,需要建立連接。 但是之后的訪問,均會(huì)復(fù)用之前創(chuàng)建的連接,直接執(zhí)行SQL語句。
優(yōu)點(diǎn):
較少了網(wǎng)絡(luò)開銷
系統(tǒng)的性能會(huì)有一個(gè)實(shí)質(zhì)的提升
沒了麻煩的TIME_WAIT狀態(tài)
五、常用連接池對(duì)比
目前存在多個(gè)開源的java數(shù)據(jù)庫連接池,這些連接池都是在java.sql基礎(chǔ)上編寫而成。
建數(shù)據(jù)庫test,然后在創(chuàng)建表
CREATE TABLE `user` (
`userid` INT(11) NOT NULL AUTO_INCREMENT,
`username` VARCHAR(255) DEFAULT NULL,
`password` VARCHAR(255) DEFAULT NULL,
`email` VARCHAR(255) DEFAULT NULL,
`phone` VARCHAR(255) DEFAULT NULL,
`status` VARCHAR(255) NOT NULL DEFAULT '0',
`code` VARCHAR(255) DEFAULT NULL,
PRIMARY KEY (`userid`)
) ENGINE=INNODB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8;
DBCP連接池
DBCP 是 Apache 軟件基金組織下的開源連接池實(shí)現(xiàn),使用DBCP數(shù)據(jù)源,應(yīng)用程序應(yīng)在系統(tǒng)中增加如下兩個(gè) jar 文件:
Commons-dbcp.jar:連接池的實(shí)現(xiàn)
Commons-pool.jar:連接池實(shí)現(xiàn)的依賴庫
Tomcat 的連接池正是采用該連接池來實(shí)現(xiàn)的。該數(shù)據(jù)庫連接池既可以與應(yīng)用服務(wù)器整合使用,也可由應(yīng)用程序獨(dú)立使用。
核心類:org.apache.commons.dbcp2.BasicDataSourceextends Object implements DataSource
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.tomcat.dbcp.dbcp2.BasicDataSource;
import org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory;
import org.junit.Test;
import com.alibaba.druid.pool.DruidDataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class SqlDriverManage {
private final String driverClassName = "com.mysql.cj.jdbc.Driver";
private final String url = "jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC";
private final String userName = "root";
private final String userPassword = "123456";
Connection con=null;
PreparedStatement pst=null;
ResultSet rs=null;
/*
* 使用java.sql.DriverManager類----傳統(tǒng)方式,沒有使用連接池,需要引入mysql驅(qū)動(dòng)包
*/
@Test
public void test1(){
try {
//1.驅(qū)動(dòng)注冊(cè)程序
Class.forName(driverClassName);
//2.獲取連接對(duì)象
con= DriverManager.getConnection(url,userName, userPassword);
//3.準(zhǔn)備sql
String sql="select * from user";
//4.創(chuàng)建prepareStatement
pst=con.prepareStatement(sql);
//5.執(zhí)行sql語句,得到返回結(jié)果
rs= pst.executeQuery();
//6.遍歷結(jié)果,索引從1開始
while(rs.next()){
System.out.println(rs.getString(1)+" "+rs.getString(2)+" "+rs.getString(3));
}
} catch (Exception e) {
e.printStackTrace();
}finally{
//7.關(guān)閉連接(順序:后打開的先關(guān)閉)
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(pst!=null){
try {
pst.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(con!=null){
try {
con.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
/*
* 第一種方式使用實(shí)現(xiàn)了javax.sql.DataSource接口的子類--DBCP連接池硬編碼
* 在上述代碼中添加單元測(cè)試代碼
*/
@Test
public void test2(){
try {
//1.驅(qū)動(dòng)注冊(cè)程序
BasicDataSource bds=new BasicDataSource();
bds.setDriverClassName(driverClassName);
bds.setUrl(url);
bds.setUsername(userName);
bds.setPassword(userPassword);
//2.獲取連接對(duì)象
con=bds.getConnection();
//3.準(zhǔn)備sql語句
String sql="select * from user";
//4.創(chuàng)建prepareStatement
pst=con.prepareStatement(sql);
//5.執(zhí)行sql語句,得到返回結(jié)果
rs= pst.executeQuery();
//6.遍歷結(jié)果,索引從1開始
while(rs.next()){
System.out.println(rs.getString(1)+" "+rs.getString(2)+" "+rs.getString(3));
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/*
*第二種方式使用實(shí)現(xiàn)了javax.sql.DataSource接口的子類--DBCP連接池軟編碼
*/
@Test
public void test3(){
try {
//1.驅(qū)動(dòng)注冊(cè)程序
Properties pro=new Properties();
BasicDataSource bds=null;
InputStream inStream=SqlDriverManage.class.getResourceAsStream("dbcp.properties");
pro.load(inStream);
bds=new BasicDataSourceFactory().createDataSource(pro);
//2.獲取連接對(duì)象
con=bds.getConnection();
//3.準(zhǔn)備sql語句
String sql="select * from user";
//4.創(chuàng)建prepareStatement
pst=con.prepareStatement(sql);
//5.執(zhí)行sql語句,得到返回結(jié)果
rs= pst.executeQuery();
//6.遍歷結(jié)果,索引從1開始
while(rs.next()){
System.out.println(rs.getString(1)+" "+rs.getString(2)+" "+rs.getString(3));
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#dbcp.properties
driverClassName=com.mysql.cj.jdbc.Driver
username=root
password=123456
url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC
在此過程中出現(xiàn)的問題
解決方法 添加tomcat斌目錄下的tomcat-juli.jar
解決方法:
- DBCP連接池配置文件中的key與BasicDataSouce中的屬性一樣
- URl后追加allowPublicKeyRetrieval=true
C3P0連接池:
最常用的連接池技術(shù)!Spring框架,默認(rèn)支持C3P0連接池技術(shù)!
需要引入c3p0-0.9.1.2.jar
核心類:com.mchange.v2.c3p0.ComboPooledDataSourceimplements PooledDataSource extends DataSource
/*
* 使用實(shí)現(xiàn)了javax.sql.DataSource接口的子類--c3p0連接池硬編碼
*/
@Test
public void test4(){
try {
//1.驅(qū)動(dòng)注冊(cè)程序
ComboPooledDataSource cpd=new ComboPooledDataSource();
cpd.setDriverClass(driverClassName);
cpd.setJdbcUrl(url);
cpd.setUser(userName);
cpd.setPassword(userPassword);
//2.獲取連接對(duì)象
con=cpd.getConnection();
//3.準(zhǔn)備sql語句
String sql="select * from user";
//4.創(chuàng)建prepareStatement
pst=con.prepareStatement(sql);
//5.執(zhí)行sql語句,得到返回結(jié)果
rs= pst.executeQuery();
//6.遍歷結(jié)果,索引從1開始
while(rs.next()){
System.out.println(rs.getString(1)+" "+rs.getString(2)+" "+rs.getString(3));
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/*
* 使用實(shí)現(xiàn)了javax.sql.DataSource接口的子類--c3p0連接池配置文件xml
*/
@Test
public void test5(){
try {
//1.驅(qū)動(dòng)注冊(cè)程序
ComboPooledDataSource cpd=new ComboPooledDataSource("mysql-config");
//ComboPooledDataSource cpd=new ComboPooledDataSource();
//2.獲取連接對(duì)象
con=cpd.getConnection();
//3.準(zhǔn)備sql語句
String sql="select * from user";
//4.創(chuàng)建prepareStatement
pst=con.prepareStatement(sql);
//5.執(zhí)行sql語句,得到返回結(jié)果
rs= pst.executeQuery();
//6.遍歷結(jié)果,索引從1開始
while(rs.next()){
System.out.println(rs.getString(1)+" "+rs.getString(2)+" "+rs.getString(3));
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
<!--自動(dòng)加載src下c3p0的配置文件【c3p0-config.xml】,必須是放在src下。-->
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<default-config>
<property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC</property>
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
<property name="user">root</property>
<property name="password">123456</property>
</default-config>
<named-config name="mysql-config">
<property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC</property>
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
<property name="user">root</property>
<property name="password">123456</property>
</named-config>
</c3p0-config>
在此過程中出現(xiàn)的問題
DRUID簡(jiǎn)介
Druid是阿里巴巴開發(fā)的號(hào)稱為監(jiān)控而生的數(shù)據(jù)庫連接池??梢员O(jiān)控?cái)?shù)據(jù)庫訪問性能,Druid內(nèi)置提供了一個(gè)功能強(qiáng)大的StatView插件,能夠詳細(xì)統(tǒng)計(jì)SQL的執(zhí)行性能,這對(duì)于線上分析數(shù)據(jù)庫訪問性能有幫助。
核心類 com.alibaba.druid.pool.DruidDataSource extends DruidAbstractDataSource implements DataSource
/*
* 使用實(shí)現(xiàn)了javax.sql.DataSource接口的子類--druid連接池硬編碼
*/
@Test
public void test6(){
try {
//1.驅(qū)動(dòng)注冊(cè)程序
DruidDataSource dds=new DruidDataSource();
dds.setDriverClassName(driverClassName);
dds.setUrl(url);
dds.setUsername(userName);
dds.setPassword(userPassword);
//2.獲取連接對(duì)象
con=dds.getConnection();
//3.準(zhǔn)備sql語句
String sql="select * from user";
//4.創(chuàng)建prepareStatement
pst=con.prepareStatement(sql);
//5.執(zhí)行sql語句,得到返回結(jié)果
rs= pst.executeQuery();
//6.遍歷結(jié)果,索引從1開始
while(rs.next()){
System.out.println(rs.getString(1)+" "+rs.getString(2)+" "+rs.getString(3));
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/*
* 使用實(shí)現(xiàn)了javax.sql.DataSource接口的子類--druid連接池軟編碼
*/
@Test
public void test7(){
try {
//1.驅(qū)動(dòng)注冊(cè)程序
Properties pro=new Properties();
DataSource dds=null;
InputStream inStream=SqlDriverManage.class.getResourceAsStream("druid.properties");
pro.load(inStream);
dds=com.alibaba.druid.pool.DruidDataSourceFactory.createDataSource(pro);
//2.獲取連接對(duì)象
con=dds.getConnection();
//3.準(zhǔn)備sql語句
String sql="select * from user";
//4.創(chuàng)建prepareStatement
pst=con.prepareStatement(sql);
//5.執(zhí)行sql語句,得到返回結(jié)果
rs= pst.executeQuery();
//6.遍歷結(jié)果,索引從1開始
while(rs.next()){
System.out.println(rs.getString(1)+" "+rs.getString(2)+" "+rs.getString(3));
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#druid.properties
driverClassName=com.mysql.cj.jdbc.Driver
username=root
password=123456
url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=truecharacterEncoding=UTF-8&useSSL=false&serverTimezone=UTC
網(wǎng)站題目:數(shù)據(jù)庫常用連接池總結(jié)
標(biāo)題網(wǎng)址:http://aaarwkj.com/article20/psopjo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供軟件開發(fā)、移動(dòng)網(wǎng)站建設(shè)、網(wǎng)站制作、品牌網(wǎng)站建設(shè)、微信小程序、企業(yè)網(wǎng)站制作
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)