日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

数据库连接池技术详解【吐血整理,疯狂推荐】

發布時間:2024/2/28 数据库 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据库连接池技术详解【吐血整理,疯狂推荐】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

今天來講一下數據庫連接池技術.其實這個名詞也就是聽起來高大上一點,實際上并不是很復雜的內容,相信在我的講解下,并且自己實際的將代碼寫一遍之后,能夠對這項技術有較為深刻的理解.廢話不多說,開始講解.

數據庫連接池技術概述

所謂的數據庫連接池技術,就是用來分配,管理,釋放數據庫連接的.你也許會問,好像我直接用JDBC也能夠實現這些功能吧.
嗯,你說的沒錯,JDBC確實也可以,但是,你記不記得,我們使用JDBC技術的時候,每次用完了,是不是都會將連接關閉;等到下一次再用的時候,是不是都得將數據庫連接再打開?
實際上,數據庫鏈接資源是十分寶貴的,我們在小型的項目中還看不出來,在高并發的項目中,你會發現,這樣頻繁的打開和關閉數據庫鏈接是對服務器的一種摧殘,十分影響效率.
那么,數據庫連接池是如何做的呢?
實現思路是這樣的:在每次有訪問的時候,數據庫連接池會給用戶分配一個數據庫連接,當用戶用完了連接之后,連接池再將連接回收,放回一個連接集合中.
原理就是這樣的,我們來看一下這張圖加深印象

這樣你可能還是不太清楚,而且,數據庫連接池要考慮的東西要比上面說的更復雜,不過不要害怕,我通過實際的代碼來幫你理解一下.
備注:下面的代碼是自己實現一個簡單的數據庫連接池,著重了解數據庫連接池的原理.

自己實現一個數據庫連接池

注意:下面的代碼我是分塊講解的,你一個個粘貼下來,最后肯定也是能運行的,為了方便,我會在講完之后,給出完整的實現代碼.

  • 定義初始化連接數目,最大連接數以及當前已經連接的數目
    一開始,當數據庫連接池啟動的時候,為了實現上面的需求,我們肯定是要先給出幾個已經完成的連接的,這樣用戶訪問的時候就能直接拿到了;此外,當某一段時間的訪問用戶超過我定義的連接池中的連接個數,肯定是要額外新建連接給用戶使用;當然,這個新建的連接肯定是不能無限制的,否則還是會很影響效率的,所以,我們還要定義最大的連接數.
private final int init_count = 3; //初始化鏈接數目 private final int max_count = 6; //最大連接數 private int current_count = 0; //到當前連接數
  • 那么,我們一開始新建的連接池要放在哪里供用戶使用呢?肯定是要創建一個連接集合的,這樣的操作比較方便.至于為什么要使用LinkedList這樣一個集合,一會就會介紹的.
private LinkedList<Connection> pool = new LinkedList<Connection>();
  • 剛才說了,一開始我們肯定是要初始化連接給用戶使用的,那么,就需要在連接池啟動的時候就新建一定數量的鏈接.分析后發現,放在構造函數中初始化鏈接是最好不過的了,最后再將連接放在鏈接集合中.
//構造函數,初始化鏈接放入連接池public MyPool() {for (int i=0;i<init_count;i++){//記錄當前連接數current_count++;//createConnection是自定義的創建鏈接函數.Connection connection = createConnection();pool.addLast(connection);}}
  • 創建一個新的連接,這個就沒啥好說的了,畢竟你要的鏈接都是從這來的.
public Connection createConnection() {Class.forName("com.mysql.jdbc.Driver");Connection connection =DriverManager.getConnection("jdbc:mysql://localhost:3306/keyan","root","root");return connection;
  • 獲取鏈接
    當用戶來訪問的時候,我們肯定是要給用戶一個連接的,如果池中沒有連接了(所有連接均被占用),那么就要創建新的連接,使用createConnection()函數,當然,這個連接的個數肯定是不能超過最大連接數的.如果不滿足這兩個條件,那么直接拋出異常.
public Connection getConnection() {if (pool.size() > 0){//removeFirst刪除第一個并且返回//現在你一定看懂了我說的為什要用LinkedList了吧,因為下面的這個//removeFirst()方法會將集合中的第一個元素刪除,但是還會返回第一個元素//這樣就省去了我們很多不必要的麻煩return pool.removeFirst();}if (current_count < max_count){//記錄當前使用的連接數current_count++;//創建鏈接return createConnection();}throw new RuntimeException("當前鏈接已經達到最大連接數"); }
  • 釋放資源
    當用戶使用完了連接之后,我們要做的并不是關閉連接,而是將連接重新放入資源池LinkedList之中,這樣就省去了一遍又一遍的連接關閉.這個就是連接池的核心內容.是不是很簡單?
public void releaseConnection(Connection connection){if (pool.size() < init_count){pool.addLast(connection);current_count--;}else {try {connection.close();} catch (SQLException e) {e.printStackTrace();}} }

整個的實現過程就是這樣的,下面我把全部的代碼貼出來,方便大家學習.

//單元測試 @Test public class MyPool {private final int init_count = 3; //初始化鏈接數目private final int max_count = 6; //最大private int current_count = 0; //到當前連接數//連接池,用來存放初始化鏈接private LinkedList<Connection> pool = new LinkedList<Connection>();//構造函數,初始化鏈接放入連接池public MyPool() {for (int i=0;i<init_count;i++){//記錄當前連接數current_count++;Connection connection = createConnection();pool.addLast(connection);}}//創建新的連接public Connection createConnection() {try {Class.forName("com.mysql.jdbc.Driver");Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/keyan","root","root");return connection;}catch (Exception e){System.out.println("數據庫鏈接異常");throw new RuntimeException();}}//獲取鏈接public Connection getConnection() {if (pool.size() > 0){//removeFirst刪除第一個并且返回return pool.removeFirst();}if (current_count < max_count){//記錄當前使用的連接數current_count++;//創建鏈接return createConnection();}throw new RuntimeException("當前鏈接已經達到最大連接數");}//釋放鏈接public void releaseConnection(Connection connection){if (pool.size() < init_count){pool.addLast(connection);current_count--;}else {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}

自己跑了一遍代碼之后,你是不是發現原來看起來很復雜的技術,并不像我們想得那樣?
好了,介紹完了基本的數據庫連接池技術原理之后,我們就要介紹兩個開源的優秀的數據連接池技術.
其實,真正的數據庫連接池要考慮的東西比我們剛才寫的這玩意復雜,現階段不需要我們寫這樣復雜的東西,不過如果你感興趣的話,可以看看數據庫連接池的源代碼--沒錯,這兩個連接池都是開源的.OK,接下來就開始吧!

優秀的數據庫連接池

首先,sun公司規定,連接池技術需實現javax.sql.DataSource接口,也就是說,如果你要自己實現數據庫連接池,那么就必須實現這個接口.是不是很牛比的樣子,實際上,作為標準制定方,sun公司還是有很多要求的,這是作為標準制定者的權利,所以,企業或者國家往往會對一些關鍵技術標準的制定打得頭破血流.額,扯遠了...

DBPC

其實,你可能不知道,如果你的tomcat經過特殊的配置,也是可以作為數據庫連接池使用的,因為tomcat內置的就是DBPC…
想要使用DBPC,你必須導入三個jar文件:commons-dbcp2-2.2.0.jar,commons-pool2-2.5.0.jar,commons-logging-1.2.jar.我想,以你的聰明才智,想要獲取這三個jar文件,一定是小菜一疊,這是一個軟件開發者的必備技能--學會如何搜索.
使用起來就非常簡單了.使用的方式主要有兩種,一種是硬編碼的方式,就是自己手動設置各種參數,另外一種就是配置相應的配置文件,然后載入就行了.

硬編碼實現DBPC

BasicDataSource dataSource = new BasicDataSource(); //參數配置:初始化連接數,最大連接數,連接字符串,驅動,用戶,密碼 dataSource.setInitialSize(3); //最大初始化鏈接 dataSource.setMaxTotal(6); //最大鏈接 dataSource.setMaxIdle(3000); //最大空閑時間 dataSource.setUrl("jdbc:mysql:///keyan"); //url dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUsername("root"); dataSource.setPassword("root");//獲取鏈接 Connection connection = dataSource.getConnection(); connection.prepareStatement("SELECT * FROM e_person").execute(); connection.close();

使用查詢的時候,只需要按照原來JDBC的操作方式就行了,這個沒啥好說的,按照我上面的配置方式實現就行了,一定不要忘記導入包.

配置文件方式實現

//創建properties配置文件 Properties properties = new Properties(); //獲取文件流 InputStream in = DBCPTest.class.getResourceAsStream("db.properties"); //加載配置文件 properties.load(in); //創建數據源對象 BasicDataSource dataSource = BasicDataSourceFactory.createDataSource(properties);//獲取鏈接 Connection connection = dataSource.getConnection(); ResultSet resultSet = connection.prepareStatement("SELECT * FROM e_person").executeQuery(); while (resultSet.next()){System.out.println(resultSet.getString("work_name")); } connection.close();

上面是基本的操作流程,下面我們看一下這個xml文件的配置
文件db.properties

url=jdbc:mysql:///keyan driverClassName=com.mysql.jdbc.Driver username=root password=root initialSize=3 maxActive=6 maxIdle=3000

特別要注意的一點是,這個配置文件一定要放在和你的這DBPC類放在同一個包下.
都完成了之后,直接用就可以了.

C3P0

c3p0同樣是非常優秀的連接池技術,這個需要導入的文件比較少,只有一個c3p0-0.9.1.2.jar.自己去網站上找一下就好了.
使用c3p0同樣是有兩種方式,分別也是硬編碼方式和配置文件方式.

硬編碼方式

//配置相關的參數 ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setJdbcUrl("jdbc:mysql:///keyan"); dataSource.setDriverClass("com.mysql.jdbc.Driver"); dataSource.setUser("root"); dataSource.setPassword("root"); dataSource.setInitialPoolSize(3); dataSource.setMaxPoolSize(6); dataSource.setMaxIdleTime(1000);Connection connection = dataSource.getConnection(); //sql語句 ResultSet resultSet = connection.prepareStatement("SELECT * FROM e_project").executeQuery(); while (resultSet.next()){System.out.println(resultSet.getString("project_name")); } connection.close();

和上面一樣,簡單的使用一下就行了,知道如何使用就行.至于更加深層次的東西,有興趣的話慢慢研究吧.

配置文件方式

ComboPooledDataSource dataSource = new ComboPooledDataSource(); Connection connection = dataSource.getConnection(); ResultSet resultSet = connection.prepareStatement("SELECT * FROM e_project").executeQuery(); while (resultSet.next()){System.out.println(resultSet.getString("project_name")); } connection.close();

乍一看,你可能會問,不是配置文件方式實現嗎?沒錯,只是這個是隱式的調用,不需要你實現,只需要新建一個ComboPooledDataSource對象就行了,默認調用xml文件,文件路徑是src根目錄.也就是說,你只需要將配置文件寫在src目錄下就行了.重點是如何寫這個xml文件.
注意,文件名c3p0-config.xml,這個文件名不能改,必須是這個,文件路徑必須是src根目錄,否則讀取不到.

<c3p0-config><default-config><property name="jdbcUrl">jdbc:mysql://localhost:3306/test</property><property name="driverClass">com.mysql.jdbc.Driver</property><property name="user">root</property><property name="password">root</property><property name="initialPoolSize">3</property><property name="maxPoolSize">6</property><property name="maxIdleTime">1000</property></default-config> </c3p0-config>

配置文件的參數大體上用到的就這么多,當然,你也可以去找一下相關的資料,了解一下更加詳細的參數意義,這些參數,我么日常使用足夠了.

補充內容:數據庫連接池的優點

資源重用

由于數據庫連接得以重用,避免了頻繁創建,釋放連接引起的大量性能開銷。在減少系統消耗的基礎上,另一方面也增加了系統運行環境的平穩性。

更快的系統反應速度

數據庫連接池在初始化過程中,往往已經創建了若干數據庫連接置于連接池中備用。此時連接的初始化工作均已完成。對于業務請求處理而言,直接利用現有可用連接,避免了數據庫連接初始化和釋放過程的時間開銷,從而減少了系統的響應時間

新的資源分配手段

對于多應用共享同一數據庫的系統而言,可在應用層通過數據庫連接池的配置,實現某一應用最大可用數據庫連接數的限制,避免某一應用獨占所有的數據庫資源

統一的連接管理,避免數據庫連接泄露:

在較為完善的數據庫連接池實現中,可根據預先的占用超時設定,強制回收被占用連接,從而避免了常規數據庫連接操作中可能出現的資源泄露。

總結

以上是生活随笔為你收集整理的数据库连接池技术详解【吐血整理,疯狂推荐】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。