国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Mybatis引出的一系列問題-JDBC 的探究

這篇具有很好參考價(jià)值的文章主要介紹了Mybatis引出的一系列問題-JDBC 的探究。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

1 引入對(duì)JDBC的理解-1

Mybatis引出的一系列問題-JDBC 的探究,mybaits,mybatis,oracle,數(shù)據(jù)庫
一般來說,Java應(yīng)用程序訪問數(shù)據(jù)庫的過程是:

  1. 裝載數(shù)據(jù)庫驅(qū)動(dòng)程序;
  2. 通過jdbc建立數(shù)據(jù)庫連接;
  3. 訪問數(shù)據(jù)庫,執(zhí)行sql語句;
  4. 斷開數(shù)據(jù)庫連接。
Public void FindAllUsers(){
    //1、裝載sqlserver驅(qū)動(dòng)對(duì)象
    DriverManager.registerDriver(new SQLServerDriver());             
    //2、通過JDBC建立數(shù)據(jù)庫連接
    Connection con =DriverManager.getConnection("jdbc:sqlserver://192.168.2.6:1433;DatabaseName=customer", "sa", "123");            
    //3、創(chuàng)建狀態(tài)會(huì)話
    Statement state =con.createStatement();           
    //4、查詢數(shù)據(jù)庫并返回結(jié)果
    ResultSet result =state.executeQuery("select * from users");           
    //5、輸出查詢結(jié)果
    while(result.next()){
        System.out.println(result.getString("email"));
    }            
    //6、斷開數(shù)據(jù)庫連接
    result.close();
    state.close();
    con.close();
}

程序開發(fā)過程中,存在很多問題: 首先,每一次web請(qǐng)求都要建立一次數(shù)據(jù)庫連接。建立連接是一個(gè)費(fèi)時(shí)的活動(dòng),每次都得花費(fèi)0.05s~1s的時(shí)間,而且系統(tǒng)還要分配內(nèi)存資源。 這個(gè)時(shí)間對(duì)于一次或幾次web請(qǐng)求數(shù)據(jù)庫操作,或許感覺不出系統(tǒng)有多大的開銷??墒菍?duì)于現(xiàn)在的web應(yīng)用,尤其是大型電子商務(wù)網(wǎng)站,同時(shí)有幾百人甚至幾千人在線是很正常的事。

在這種情況下,頻繁的進(jìn)行數(shù)據(jù)庫連接操作勢(shì)必占用很多的系統(tǒng)資源,網(wǎng)站的響應(yīng)速度必定下降,嚴(yán)重的甚至?xí)斐煞?wù)器的崩潰。 不是危言聳聽,這就是制約某些電子商務(wù)網(wǎng)站發(fā)展的技術(shù)瓶頸問題。其次,對(duì)于每一次數(shù)據(jù)庫連接,使用完后都得斷開。 但是,如果程序出現(xiàn)異常而未能關(guān)閉,將會(huì)導(dǎo)致數(shù)據(jù)庫系統(tǒng)中的內(nèi)存泄漏,最終將不得不重啟數(shù)據(jù)庫。 還有,這種開發(fā)不能控制被創(chuàng)建的連接對(duì)象數(shù),系統(tǒng)資源會(huì)被毫無顧及的分配出去,如連接過多,也可能導(dǎo)致內(nèi)存泄漏,服務(wù)器崩潰。

上述的用戶查詢案例,如果同時(shí)有1000人訪問,就會(huì)不斷的有數(shù)據(jù)庫連接、斷開操作:
Mybatis引出的一系列問題-JDBC 的探究,mybaits,mybatis,oracle,數(shù)據(jù)庫
通過上面的分析,我們可以看出來,“數(shù)據(jù)庫連接”是一種稀缺的資源,為了保障網(wǎng)站的正常使用,應(yīng)該對(duì)其進(jìn)行妥善管理。其實(shí),我們查詢完數(shù)據(jù)庫后,如果不關(guān)閉連接,而是暫時(shí)存放起來,當(dāng)別人使用時(shí),把這個(gè)連接給他們使用,就避免了一次建立數(shù)據(jù)庫連接和斷開的操作時(shí)間消耗。原理如下:
Mybatis引出的一系列問題-JDBC 的探究,mybaits,mybatis,oracle,數(shù)據(jù)庫
由上面的分析可以看出,問題的根源就在于對(duì)數(shù)據(jù)庫連接資源的低效管理。我們知道,對(duì)于共享資源,有一個(gè)很著名的設(shè)計(jì)模式:資源池(resource pool)。該模式正是為了解決資源的頻繁分配、釋放所造成的問題。 為解決上述問題,可以采用數(shù)據(jù)庫連接池技術(shù)。

數(shù)據(jù)庫連接池的基本思想就是為數(shù)據(jù)庫連接建立一個(gè)“緩沖池”。預(yù)先在緩沖池中放入一定數(shù)量的連接,當(dāng)需要建立數(shù)據(jù)庫連接時(shí),只需從“緩沖池”中取出一個(gè),使用完畢之后再放回去。

我們可以通過設(shè)定連接池最大連接數(shù)來防止系統(tǒng)無盡的與數(shù)據(jù)庫連接。更為重要的是我們可以通過連接池的管理機(jī)制——監(jiān)視數(shù)據(jù)庫的連接的數(shù)量、使用情況,為系統(tǒng)開發(fā)、測(cè)試及性能調(diào)整提供依據(jù)。

我們自己嘗試開發(fā)一個(gè)連接池,來為上面的查詢業(yè)務(wù)提供數(shù)據(jù)庫連接服務(wù):

  1. 編寫class 實(shí)現(xiàn)DataSource 接口
  2. 在class構(gòu)造器一次性創(chuàng)建10個(gè)連接,將連接保存LinkedList中
  3. 實(shí)現(xiàn)getConnection 從 LinkedList中返回一個(gè)連接
  4. 提供將連接放回連接池中方法
public class MyDataSource implements DataSource {
              //鏈表 --- 實(shí)現(xiàn)棧結(jié)構(gòu)
                privateLinkedList<Connection> dataSources = new LinkedList<Connection>();
              //初始化連接數(shù)量
              publicMyDataSource() {
                     //一次性創(chuàng)建10個(gè)連接
                     for(int i = 0; i < 10; i++) {
                            try {
                               //1、裝載sqlserver驅(qū)動(dòng)對(duì)象
                               DriverManager.registerDriver(new SQLServerDriver());
                               //2、通過JDBC建立數(shù)據(jù)庫連接
                               Connection con =DriverManager.getConnection(
                                  "jdbc:sqlserver://192.168.2.6:1433;DatabaseName=customer", "sa", "123");
                               //3、將連接加入連接池中
                               dataSources.add(con);
                            } catch (Exception e) {
                               e.printStackTrace();
                            }
                     }
              }

              @Override
              publicConnection getConnection() throws SQLException {
                     //取出連接池中一個(gè)連接
                     finalConnection conn = dataSources.removeFirst(); // 刪除第一個(gè)連接返回
                     return conn;
              }

              //將連接放回連接池
              publicvoid releaseConnection(Connection conn) {
                     dataSources.add(conn);
              }
       }


       //查詢所有用戶
       Public void FindAllUsers(){
              //1、使用連接池建立數(shù)據(jù)庫連接
              MyDataSource dataSource = new MyDataSource();
              Connection conn =dataSource.getConnection();        
              //2、創(chuàng)建狀態(tài)
              Statement state =con.createStatement();           
              //3、查詢數(shù)據(jù)庫并返回結(jié)果
              ResultSet result =state.executeQuery("select * from users");           
              //4、輸出查詢結(jié)果
              while(result.next()){
                     System.out.println(result.getString("email"));
              }            
              //5、斷開數(shù)據(jù)庫連接
              result.close();
              state.close();
              //6、歸還數(shù)據(jù)庫連接給連接池
              dataSource.releaseConnection(conn);
        }

這就是數(shù)據(jù)庫連接池的原理,它大大提供了數(shù)據(jù)庫連接的利用率,減小了內(nèi)存吞吐的開銷。我們?cè)陂_發(fā)過程中,就不需要再關(guān)心數(shù)據(jù)庫連接的問題,自然有數(shù)據(jù)庫連接池幫助我們處理,這回放心了吧。但連接池需要考慮的問題不僅僅如此,下面我們就看看還有哪些問題需要考慮。

1、并發(fā)問題
為了使連接管理服務(wù)具有最大的通用性,必須考慮多線程環(huán)境,即并發(fā)問題。這個(gè)問題相對(duì)比較好解決,因?yàn)閖ava語言自身提供了對(duì)并發(fā)管理的支持,使用synchronized關(guān)鍵字即可確保線程是同步的。使用方法為直接在類方法前面加上synchronized關(guān)鍵字,如:

public synchronized connection getconnection()

2、多數(shù)據(jù)庫服務(wù)器和多用戶
對(duì)于大型的企業(yè)級(jí)應(yīng)用,常常需要同時(shí)連接不同的數(shù)據(jù)庫(如連接oracle和sybase)。如何連接不同的數(shù)據(jù)庫呢?我們采用的策略是:

設(shè)計(jì)一個(gè)符合單例模式的連接池管理類,在連接池管理類的唯一實(shí)例被創(chuàng)建時(shí)讀取一個(gè)資源文件,其中資源文件中存放著多個(gè)數(shù)據(jù)庫的url地址等信息。根據(jù)資源文件提供的信息,創(chuàng)建多個(gè)連接池類的實(shí)例,每一個(gè)實(shí)例都是一個(gè)特定數(shù)據(jù)庫的連接池。連接池管理類實(shí)例為每個(gè)連接池實(shí)例取一個(gè)名字,通過不同的名字來管理不同的連接池。

對(duì)于同一個(gè)數(shù)據(jù)庫有多個(gè)用戶使用不同的名稱和密碼訪問的情況,也可以通過資源文件處理,即在資源文件中設(shè)置多個(gè)具有相同url地址,但具有不同用戶名和密碼的數(shù)據(jù)庫連接信息。

3、事務(wù)處理
我們知道,事務(wù)具有原子性,此時(shí)要求對(duì)數(shù)據(jù)庫的操作符合“all-all-nothing”原則即對(duì)于一組sql語句要么全做,要么全不做。在java語言中,connection類本身提供了對(duì)事務(wù)的支持,可以通過設(shè)置connection的autocommit屬性為false 然后顯式的調(diào)用commit或rollback方法來實(shí)現(xiàn)。

但要高效的進(jìn)行connection復(fù)用,就必須提供相應(yīng)的事務(wù)支持機(jī)制。可采用每一個(gè)事務(wù)獨(dú)占一個(gè)連接來實(shí)現(xiàn),這種方法可以大大降低事務(wù)管理的復(fù)雜性。

4、連接池的分配與釋放
連接池的分配與釋放,對(duì)系統(tǒng)的性能有很大的影響。合理的分配與釋放,可以提高連接的復(fù)用度,從而降低建立新連接的開銷,同時(shí)還可以加快用戶的訪問速度。

對(duì)于連接的管理可使用空閑池。即把已經(jīng)創(chuàng)建但尚未分配出去的連接按創(chuàng)建時(shí)間存放到一個(gè)空閑池中。

每當(dāng)用戶請(qǐng)求一個(gè)連接時(shí),系統(tǒng)首先檢查空閑池內(nèi)有沒有空閑連接。如果有就把建立時(shí)間最長(通過容器的順序存放實(shí)現(xiàn))的那個(gè)連接分配給他(實(shí)際是先做連接是否有效的判斷,如果可用就分配給用戶,如不可用就把這個(gè)連接從空閑池刪掉,重新檢測(cè)空閑池是否還有連接);

如果沒有則檢查當(dāng)前所開連接池是否達(dá)到連接池所允許的最大連接數(shù)(maxconn)如果沒有達(dá)到,就新建一個(gè)連接,如果已經(jīng)達(dá)到,就等待一定的時(shí)間(timeout)。

如果在等待的時(shí)間內(nèi)有連接被釋放出來就可以把這個(gè)連接分配給等待的用戶,如果等待時(shí)間超過預(yù)定時(shí)間timeout 則返回空值(null)。

系統(tǒng)對(duì)已經(jīng)分配出去正在使用的連接只做計(jì)數(shù),當(dāng)使用完后再返還給空閑池。對(duì)于空閑連接的狀態(tài),可開辟專門的線程定時(shí)檢測(cè),這樣會(huì)花費(fèi)一定的系統(tǒng)開銷,但可以保證較快的響應(yīng)速度。也可采取不開辟專門線程,只是在分配前檢測(cè)的方法。

5、連接池的配置與維護(hù)
連接池中到底應(yīng)該放置多少連接,才能使系統(tǒng)的性能最佳?系統(tǒng)可采取設(shè)置最小連接數(shù)(minconn)和最大連接數(shù)(maxconn)來控制連接池中的連接。

最小連接數(shù)是系統(tǒng)啟動(dòng)時(shí)連接池所創(chuàng)建的連接數(shù)。如果創(chuàng)建過多,則系統(tǒng)啟動(dòng)就慢,但創(chuàng)建后系統(tǒng)的響應(yīng)速度會(huì)很快;如果創(chuàng)建過少,則系統(tǒng)啟動(dòng)的很快,響應(yīng)起來卻慢。

最大連接數(shù)是連接池中允許連接的最大數(shù)目,具體設(shè)置多少,要看系統(tǒng)的訪問量,可通過反復(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í)再去檢查。

實(shí)際開發(fā)中有成熟的開源連接池供我們使用:
理解了連接池的原理就可以了,沒有必要什么都從頭寫一遍,那樣會(huì)花費(fèi)很多時(shí)間,并且性能及穩(wěn)定性也不一定滿足要求。事實(shí)上,已經(jīng)存在很多流行的性能優(yōu)良的第三方數(shù)據(jù)庫連接池jar包供我們使用。如:

Apache commons-dbcp
c3p0
Druid
HikariCP

其中c3p0已經(jīng)很久沒有更新了,DBCP更新速度很慢,基本處于不活躍狀態(tài)。而Druid和HikariCP處于活躍狀態(tài)的更新中。

2 引入對(duì)JDBC的理解-2

數(shù)據(jù)庫應(yīng)用,在許多軟件系統(tǒng)中經(jīng)常用到,是開發(fā)中大型系統(tǒng)不可缺少的輔助。 但如果對(duì)數(shù)據(jù)庫資源沒有很好地管理(如:沒有及時(shí)回收數(shù)據(jù)庫的游標(biāo)(ResultSet)、Statement、連接 (Connection)等資源),往往會(huì)直接導(dǎo)致系統(tǒng)的穩(wěn)定。 這類不穩(wěn)定因素,不單單由數(shù)據(jù)庫或者系統(tǒng)本身一方引起,只有系統(tǒng)正式使用后,隨著流量、用戶的增加,才會(huì)逐步顯露。

對(duì)于一個(gè)簡單的數(shù)據(jù)庫應(yīng)用,由于對(duì)于數(shù)據(jù)庫的訪問不是很頻繁。這時(shí)可以簡單地在需要訪問數(shù)據(jù)庫時(shí),就新創(chuàng)建一個(gè)連接,用完后就關(guān)閉它,這樣做也不會(huì)帶來什么明顯的性能上的開銷。 但是對(duì)于一個(gè)復(fù)雜的數(shù)據(jù)庫應(yīng)用,情況就完全不同了。頻繁的建立、關(guān)閉連接,會(huì)極大的減低系統(tǒng)的性能,因?yàn)閷?duì)于連接的使用成了系統(tǒng)性能的瓶頸。

連接復(fù)用: 通過建立一個(gè)數(shù)據(jù)庫連接池以及一套連接使用管理策略,使得一個(gè)數(shù)據(jù)庫連接可以得到高效、安全的復(fù)用,避免了數(shù)據(jù)庫連接頻繁建立、關(guān)閉的開銷。 對(duì)于共享資源,有一個(gè)很著名的設(shè)計(jì)模式:資源池。該模式正是為了解決資源頻繁分配、釋放所造成的問題的。 把該模式應(yīng)用到數(shù)據(jù)庫連接管理領(lǐng)域,就是建立一個(gè)數(shù)據(jù)庫連接池,提供一套高效的連接分配、使用策略,最終目標(biāo)是實(shí)現(xiàn)連接的高效、安全的復(fù)用。

數(shù)據(jù)庫連接池的基本原理: 在內(nèi)部對(duì)象池中維護(hù)一定數(shù)量的數(shù)據(jù)庫連接,并對(duì)外暴露數(shù)據(jù)庫連接獲取和返回方法。 如:外部使用者可通過 getConnection 方法獲取連接,使用完畢后再通過 releaseConnection 方法將連接返回,注意此時(shí)連接并沒有關(guān)閉,而是由連接池管理器回收,并為下一次使用做好準(zhǔn)備。

數(shù)據(jù)庫連接池技術(shù)帶來的優(yōu)勢(shì)

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

2 更快的系統(tǒng)響應(yīng)速度
數(shù)據(jù)庫連接池在初始化過程中,往往已經(jīng)創(chuàng)建了若干數(shù)據(jù)庫連接置于池中備用。此時(shí)連接的初始化工作均已完成。 對(duì)于業(yè)務(wù)請(qǐng)求處理而言,直接利用現(xiàn)有可用連接,避免了數(shù)據(jù)庫連接初始化和釋放過程的時(shí)間開銷,從而縮減了系統(tǒng)整體響應(yīng)時(shí)間。

3 新的資源分配手段
對(duì)于多應(yīng)用共享同一數(shù)據(jù)庫的系統(tǒng)而言,可在應(yīng)用層通過數(shù)據(jù)庫連接的配置,實(shí)現(xiàn)數(shù)據(jù)庫連接池技術(shù),如果設(shè)計(jì)中還沒有考慮到連接池的應(yīng)用, 那么…….快在設(shè)計(jì)文檔中加上這部分的內(nèi)容吧。某一應(yīng)用最大可用數(shù)據(jù)庫連接數(shù)的限制,避免某一應(yīng)用獨(dú)占所有數(shù)據(jù)庫資源。

4 統(tǒng)一的連接管理,避免數(shù)據(jù)庫連接泄漏
在較為完備的數(shù)據(jù)庫連接池實(shí)現(xiàn)中,可根據(jù)預(yù)先的連接占用超時(shí)設(shè)定,強(qiáng)制收回被占用連接。從而避免了常規(guī)數(shù)據(jù)庫連接操作中可能出現(xiàn)的資源泄漏。

一個(gè)最小化的數(shù)據(jù)庫連接池實(shí)現(xiàn): 在基于Java開發(fā)的系統(tǒng)中,JDBC是程序員和數(shù)據(jù)庫打交道的主要途徑,提供了完備的數(shù)據(jù)庫操作方法接口。 但考慮到規(guī)范的適用性,JDBC只提供了最直接的數(shù)據(jù)庫操作規(guī)范,對(duì)數(shù)據(jù)庫資源管理,如:對(duì)物理連接的管理及緩沖,期望第三方應(yīng)用服務(wù)器(Application Server)的提供。

應(yīng)用在獲取數(shù)據(jù)庫連接connection時(shí),需要指定使用哪種類型的Driver,在獲得特定的連接后,可按照固定的接口操作不同類型的數(shù)據(jù)庫, 如: 分別獲取Statement、執(zhí)行SQL獲得ResultSet等,如下面的例子 :

    Class.forName("com.mysql.jdbc.Driver");
    Connection conn = DriverManager.getConnection(url, username, password);
    Statement stmt = conn.createStatement();
    String sql1 = "update user set age = 100 where id = 1";
    int rows1 = stmt.executeUpdate(sql1);
    stmt.close();
    conn.close();

在完成數(shù)據(jù)操作后,一定要關(guān)閉所有涉及到的數(shù)據(jù)庫資源。這雖然對(duì)應(yīng)用程序的邏輯沒有任何影響,但是關(guān)鍵的操作。 上面是個(gè)簡單的例子,如果攙和眾多的if-else、exception,資源的管理也難免百密一疏,Java系統(tǒng)也同樣會(huì)面臨崩潰的惡運(yùn)。 所以數(shù)據(jù)庫資源的管理依賴于應(yīng)用系統(tǒng)本身,是不安全、不穩(wěn)定的一種隱患。

JDBC連接池: 在標(biāo)準(zhǔn)JDBC對(duì)應(yīng)用的接口中,并沒有提供資源的管理方法。所以,缺省的資源管理由應(yīng)用自己負(fù)責(zé)。雖然在JDBC規(guī)范中,多次提及資源的關(guān)閉/回收及其他的合理運(yùn)用。 但最穩(wěn)妥的方式,還是為應(yīng)用提供有效的管理手段。 所以,JDBC為第三方應(yīng)用服務(wù)器(Application Server)提供了一個(gè)由數(shù)據(jù)庫廠家實(shí)現(xiàn)的管理標(biāo)準(zhǔn)接口:連接緩沖(connection pooling)。 引入了連接池( Connection Pool )的概念 ,也就是以緩沖池的機(jī)制管理數(shù)據(jù)庫的資源。

JDBC最常用的資源有三類: Connection數(shù)據(jù)庫連接。 Statement會(huì)話。 ResultSet結(jié)果集游標(biāo)。
Mybatis引出的一系列問題-JDBC 的探究,mybaits,mybatis,oracle,數(shù)據(jù)庫
數(shù)據(jù)庫連接池的實(shí)現(xiàn)及原理:
這是一種“爺—父—子”的關(guān)系,對(duì)Connection的管理,就是對(duì)數(shù)據(jù)庫資源的管理。舉個(gè)例子: 如果想確定某個(gè)數(shù)據(jù)庫連接(Connection)是否超時(shí),則需要確定其(所有的)子Statement是否超時(shí),同樣,需要確定所有相關(guān)的 ResultSet是否超時(shí);在關(guān)閉Connection前,需要關(guān)閉所有相關(guān)的Statement和ResultSet。因此,連接池(Connection Pool)所起到的作用,不僅僅簡單地管理Connection,還涉及到 Statement和ResultSet。

連接池(ConnectionPool)與資源管理:
ConnectionPool以緩沖池的機(jī)制,在一定數(shù)量上限范圍內(nèi),控制管理Connection,Statement和ResultSet。任何數(shù)據(jù)庫的資源是有限的,如果被耗盡,則無法獲得更多的數(shù)據(jù)服務(wù)。

在大多數(shù)情況下,資源的耗盡不是由于應(yīng)用的正常負(fù)載過高,而是程序的原因。在實(shí)際工作中,數(shù)據(jù)資源往往是瓶頸資源,不同的應(yīng)用都會(huì)訪問同一數(shù)據(jù)源。其中某個(gè)應(yīng)用耗盡了數(shù)據(jù)庫資源后,意味其他的應(yīng)用也無法正常運(yùn)行。

因此,ConnectionPool的第一個(gè)任務(wù)是限制:每個(gè)應(yīng)用或系統(tǒng)可以擁有的最大資源,也就是確定連接池的大小(PoolSize)。

ConnectionPool的第二個(gè)任務(wù):在連接池的大小(PoolSize)范圍內(nèi),最大限度地使用資源,縮短數(shù)據(jù)庫訪問的使用周期。

許多數(shù)據(jù)庫中,連接(Connection)并不是資源的最小單元,控制Statement資源比Connection更重要。以O(shè)racle為例: 每申請(qǐng)一個(gè)數(shù)據(jù)庫連接(Connection)會(huì)在物理網(wǎng)絡(luò)(如 TCP/IP網(wǎng)絡(luò))上建立一個(gè)用于通訊的連接,在此連接上還可以申請(qǐng)一定數(shù)量的Statement。同一連接可提供的活躍Statement數(shù)量可以達(dá)到幾百。 在節(jié)約網(wǎng)絡(luò)資源的同時(shí),縮短了每次會(huì)話周期(物理連接的建立是個(gè)費(fèi)時(shí)的操作)。
Mybatis引出的一系列問題-JDBC 的探究,mybaits,mybatis,oracle,數(shù)據(jù)庫
但在一般的應(yīng)用中,多數(shù)按照上例代碼操作,這樣有10個(gè)程序調(diào)用,則會(huì)產(chǎn)生10次物理連接,每個(gè)Statement單獨(dú)占用一個(gè)物理連接,這是極大的資源浪費(fèi)。

ConnectionPool可以解決這個(gè)問題,讓幾十、幾百個(gè)Statement只占用同一個(gè)物理連接, 發(fā)揮數(shù)據(jù)庫原有的優(yōu)點(diǎn)。通過ConnectionPool對(duì)資源的有效管理,應(yīng)用可以獲得的Statement總數(shù)到達(dá) : (并發(fā)物理連接數(shù))×(每個(gè)連接可提供的Statement數(shù)量)

例如,某種數(shù)據(jù)庫可同時(shí)建立的物理連接數(shù)為 200個(gè),每個(gè)連接可同時(shí)提供250個(gè)Statement,那么ConnectionPool最終為應(yīng)用提供的并發(fā)Statement總數(shù)為: 200 × 250 = 50,000個(gè)。這是個(gè)并發(fā)數(shù)字,很少有系統(tǒng)會(huì)突破這個(gè)量級(jí)。所以指出資源的耗盡與應(yīng)用程序直接管理有關(guān)。

簡單JDBC連接池的實(shí)現(xiàn)
在JDBC規(guī)范中,應(yīng)用通過驅(qū)動(dòng)接口(Driver Interface)直接獲取數(shù)據(jù)庫的資源。為了有效、合理地管理資源,在應(yīng)用與JDBC Driver之間,增加了連接池: Snap-ConnectionPool。
并且通過面向?qū)ο蟮臋C(jī)制,使連接池的大部分操作是透明的。

參見下圖,Snap-ConnectionPool的體系:
Mybatis引出的一系列問題-JDBC 的探究,mybaits,mybatis,oracle,數(shù)據(jù)庫
圖中所示,通過實(shí)現(xiàn)JDBC的部分資源對(duì)象接口( Connection, Statement, ResultSet ),
在 Snap-ConnectionPool內(nèi)部分別產(chǎn)生三種邏輯資源對(duì)象: PooledConnection, PooledStatement和 PooledResultSet。它們也是連接池主要的管理操作對(duì)象,并且繼承了JDBC中相應(yīng)的從屬關(guān)系。這樣的體系有以下幾個(gè)特點(diǎn):

透明性:
在不改變應(yīng)用原有的使用JDBC驅(qū)動(dòng)接口的前提下,提供資源管理的服務(wù)。
資源封裝:
復(fù)雜的資源管理被封裝在 Snap-ConnectionPool內(nèi)部,不需要應(yīng)用系統(tǒng)過多的干涉。管理操作的可靠性、安全性由連接池保證。應(yīng)用的干涉(如:主動(dòng)關(guān)閉資源),只起到優(yōu)化系統(tǒng)性能的作用,遺漏操作不會(huì)帶來負(fù)面影響。
資源合理應(yīng)用:
按照J(rèn)DBC中資源的從屬關(guān)系,Snap-ConnectionPool不僅對(duì)Connection進(jìn)行緩沖處理,對(duì)Statement也有相應(yīng)的機(jī)制處理。合理運(yùn)用Connection和Statement之間的關(guān)系,可以更大限度地使用資源。所以,Snap-ConnectionPool封裝了Connection資源, 通過內(nèi)部管理PooledConnection,為應(yīng)用系統(tǒng)提供更多的Statement 資源。
資源連鎖管理:
Snap-ConnectionPool包含的三種邏輯對(duì)象,繼承了JDBC中相應(yīng)對(duì)象之間的從屬關(guān)系。在內(nèi)部管理中,也依照從屬關(guān)系進(jìn)行連鎖管理。例如:判斷一個(gè)Connection是否超時(shí),需要根據(jù)所包含的Statement是否活躍;判斷Statement也要根據(jù) ResultSet的活躍程度。

連接池集中管理ConnectionManager
ConnectionPool是Snap-ConnectionPool的連接池對(duì)象。在Snap-ConnectionPool內(nèi)部,可以指定多個(gè)不同的連接池(ConnectionPool)為應(yīng)用服務(wù)。ConnectionManager管理所有的連接池,每個(gè)連接池以不同的名稱區(qū)別。通過配置文件適應(yīng)不同的數(shù)據(jù)庫種類。如下圖所示:
Mybatis引出的一系列問題-JDBC 的探究,mybaits,mybatis,oracle,數(shù)據(jù)庫
通過ConnectionManager,可以同時(shí)管理多個(gè)不同的連接池,提供通一的管理界面。在應(yīng)用系統(tǒng)中通過 ConnectionManager和相關(guān)的配置文件,可以將凌亂散落在各自應(yīng)用程序中的數(shù)據(jù)庫配置信息(包括:數(shù)據(jù)庫名、用戶、密碼等信息),集中在一個(gè)文件中。便于系統(tǒng)的維護(hù)工作。

連接池使用范例:
對(duì)上栗代碼的標(biāo)準(zhǔn)JDBC的使用范例,改為使用連接池,結(jié)果如下:

    import java.sql.*;
    import net.snapbug.util.dbtool.*;ConnectionPool dbConn = ConnectionManager .getConnectionPool("testOracle" );
    Statement st = dbConn.createStatement();
    ResultSet rs = st.executeQuery(“select * from demo_table” );
    …
    some data source operation in here
    rs.close();
    st.close();

在例子中,Snap-ConnectionPool封裝了應(yīng)用對(duì)Connection的管理。只要改變JDBC獲取Connection的方法——獲取連接池(ConnectionPool)(粗體部分),其他的數(shù)據(jù)操作都可以不做修改。

按照這樣的方式,Snap-ConnectionPool可幫助應(yīng)用有效地管理數(shù)據(jù)庫資源。
如果應(yīng)用忽視了最后資源的釋放: rs.close() 和 st.close(),連接池會(huì)通過超時(shí)(time-out)機(jī)制,自動(dòng)回收。

小結(jié):
無論是Snap-ConnectionPool還是其他的數(shù)據(jù)庫連接池,都應(yīng)當(dāng)具備一下基本功能:

  1. 對(duì)源數(shù)據(jù)庫資源的保護(hù)
  2. 充分利用發(fā)揮數(shù)據(jù)庫的有效資源
  3. 簡化應(yīng)用的數(shù)據(jù)庫接口,封閉資源管理。
  4. 對(duì)應(yīng)用遺留資源的自動(dòng)回收和整理,提高資源的再次利用率。
  5. 在這個(gè)前提下,應(yīng)用程序才能投入更多的精力于各自的業(yè)務(wù)邏輯中,數(shù)據(jù)庫資源也不再成為系統(tǒng)的瓶頸。

3 技術(shù)經(jīng)理:求求你,別再亂改數(shù)據(jù)庫連接池的大小了

基本上來說,大部分項(xiàng)目都需要跟數(shù)據(jù)庫做交互,那么,數(shù)據(jù)庫連接池的大小設(shè)置成多大合適呢? 一些開發(fā)老鳥可能還會(huì)告訴你:沒關(guān)系,盡量設(shè)置的大些,比如設(shè)置成 200,這樣數(shù)據(jù)庫性能會(huì)高些,吞吐量也會(huì)大些! 你也許會(huì)點(diǎn)頭稱是,真的是這樣嗎?看完這篇文章,也許會(huì)顛覆你的認(rèn)知哦!

可以很直接的說,關(guān)于數(shù)據(jù)庫連接池大小的設(shè)置,每個(gè)開發(fā)者都可能在一環(huán)節(jié)掉進(jìn)坑里,事實(shí)上呢,大部分程序員可能都會(huì)依靠自己的直覺去設(shè)置它的大小,設(shè)置成 100 ? 思量許久后,自顧自想,應(yīng)該差不多吧?

不妨意淫一下,你手里有個(gè)網(wǎng)站,并發(fā)壓力雖然還沒到 Facebook 那個(gè)級(jí)別,但是呢?也有個(gè)1萬上下的并發(fā)量! 也就是說差不多2萬左右的 TPS[TPS:Transactions Per Second(每秒傳輸?shù)氖挛锾幚韨€(gè)數(shù)),TPS包括一條消息入和一條消息出,加上一次用戶數(shù)據(jù)庫訪問,那么問題來了!這個(gè)網(wǎng)站的數(shù)據(jù)庫連接池應(yīng)該設(shè)置成多大合適呢? 其實(shí)這個(gè)問法本身就是有問題的,我們需要反過來問,正確問法應(yīng)該是: “這個(gè)網(wǎng)站的數(shù)據(jù)庫連接池應(yīng)該設(shè)置成多小合適呢?”

對(duì) Oracle 數(shù)據(jù)庫進(jìn)行了壓力測(cè)試,模擬 9600 個(gè)并發(fā)線程來操作數(shù)據(jù)庫,每兩次數(shù)據(jù)庫操作之間 sleep 550ms,注意,開始設(shè)置的線程池大小為 2048。

讓我們來看看數(shù)據(jù)庫連接池的大小為 2048 性能測(cè)試結(jié)果的鬼樣子: 每個(gè)請(qǐng)求要在連接池隊(duì)列里等待 33ms,獲得連接之后,執(zhí)行SQL需要耗時(shí)77ms, CPU 消耗維持在 95% 左右;

接下來,我們將連接池的大小改小點(diǎn),設(shè)置成 1024,其他測(cè)試參數(shù)不變,結(jié)果咋樣? "這里,獲取連接等待時(shí)長基本不變,但是 SQL 的執(zhí)行耗時(shí)降低了!"

哎呦,有長進(jìn)哦!

接下來,我們?cè)僭O(shè)置小些,連接池的大小降低到 96,并發(fā)數(shù)等其他參數(shù)不變,看看結(jié)果如何: 每個(gè)請(qǐng)求在連接池隊(duì)列中的平均等待時(shí)間為 1ms, SQL 執(zhí)行耗時(shí)為 2ms。

我去!什么鬼?

我們沒調(diào)整任何東西,僅僅只是將數(shù)據(jù)庫連接池的大小降低了,這樣,就能把之前平均 100ms 響應(yīng)時(shí)間縮短到了 3ms。吞吐量指數(shù)級(jí)上升??! 你這也太溜了!

為啥有這種效果? 我們不妨想一下,為啥 Nginx 內(nèi)部僅僅使用了 4 個(gè)線程,其性能就大大超越了 100 個(gè)進(jìn)程的 Apache HTTPD 呢? 追究其原因的話,回想一下計(jì)算機(jī)科學(xué)的基礎(chǔ)知識(shí),答案其實(shí)非常明顯。 要知道,即使是單核 CPU 的計(jì)算機(jī)也能“同時(shí)”運(yùn)行著數(shù)百個(gè)線程。但我們其實(shí)都知道,這只不過是操作系統(tǒng)快速切換時(shí)間片,跟我們玩的一個(gè)小把戲罷了。 一核 CPU同一時(shí)刻只能執(zhí)行一個(gè)線程,然后操作系統(tǒng)切換上下文,CPU 核心快速調(diào)度,執(zhí)行另一個(gè)線程的代碼,不停反復(fù),給我們?cè)斐闪怂羞M(jìn)程同時(shí)運(yùn)行假象。 其實(shí),在一核 CPU 的機(jī)器上,順序執(zhí)行A和B永遠(yuǎn)比通過時(shí)間分片切換“同時(shí)”執(zhí)行A和B要快,其中原因,學(xué)過操作系統(tǒng)這門課程的童鞋應(yīng)該很清楚。 一旦線程的數(shù)量超過了 CPU 核心的數(shù)量,再增加線程數(shù)系統(tǒng)就只會(huì)更慢,而不是更快,因?yàn)檫@里涉及到上下文切換耗費(fèi)的額外的性能。 說到這里,你應(yīng)該恍然大悟了 ……

當(dāng)我們?cè)趯ふ覕?shù)據(jù)庫的性能瓶頸時(shí),大致可歸為三類: CPU、 磁盤 IO 、網(wǎng)絡(luò) IO ,也許你會(huì)說,還有內(nèi)存這一因素?內(nèi)存的確是需要考慮的,但是比起磁盤IO和網(wǎng)絡(luò)IO,稍顯微不足道,這里就不加了。

假設(shè)我們不考慮磁盤 IO 和網(wǎng)絡(luò) IO,就很好定論了,在一個(gè) 8 核的服務(wù)器上,數(shù)據(jù)庫連接數(shù)/線程數(shù)設(shè)置為 8 能夠提供最優(yōu)的性能,如果再增加連接數(shù),反而會(huì)因?yàn)樯舷挛那袚Q導(dǎo)致性能下降。

大家都知道,數(shù)據(jù)庫通常把數(shù)據(jù)存儲(chǔ)在磁盤上,而磁盤呢,通常是由一些旋轉(zhuǎn)著的金屬碟片和一個(gè)裝在步進(jìn)馬達(dá)上的讀寫頭組成的。 讀/寫頭同一時(shí)刻只能出現(xiàn)在一個(gè)位置,當(dāng)它需要再次執(zhí)行讀寫操作時(shí),它必須“尋址”到另外一個(gè)位置才能完成任務(wù)。 所以呢?這里就有了尋址耗時(shí),此外還有旋轉(zhuǎn)耗時(shí),讀寫頭需要等待磁盤碟片上的目標(biāo)數(shù)據(jù)“旋轉(zhuǎn)到位”才能進(jìn)行讀寫操作。使用緩存當(dāng)然是能夠提升性能的,但上述原理仍然適用。

在這段(“I/O等待”)時(shí)間內(nèi),線程是處于“阻塞”等待狀態(tài),也就是說沒干啥正事!此時(shí)操作系統(tǒng)可以將這個(gè)空閑的CPU 核心用于服務(wù)其他線程。 這里我們可以總結(jié)一下,當(dāng)你的線程處理的是 I/O 密集型業(yè)務(wù)時(shí),便可以讓線程/連接數(shù)設(shè)置的比 CPU核心大一些,這樣就能夠在同樣的時(shí)間內(nèi),完成更多的工作,提升吞吐量。

那么問題又來了? 大小設(shè)置成多少合適呢?

這要取決于磁盤,如果你使用的是 SSD 固態(tài)硬盤,它不需要尋址,也不需要旋轉(zhuǎn)碟片。打住打住?。?!你千萬可別理所當(dāng)然的認(rèn)為:“既然SSD速度更快,我們把線程數(shù)的大小設(shè)置的大些吧!!” 結(jié)論正好相反!無需尋址和沒有旋回耗時(shí)的確意味著更少的阻塞,所以更少的線程(更接近于CPU核心數(shù))會(huì)發(fā)揮出更高的性能。只有當(dāng)阻塞密集時(shí),更多的線程數(shù)才能發(fā)揮出更好的性能。

上面我們已經(jīng)說過了磁盤 IO, 接下來我們談?wù)劸W(wǎng)絡(luò) IO!

網(wǎng)絡(luò) IO 其實(shí)也是非常相似的。通過以太網(wǎng)接口讀寫數(shù)據(jù)時(shí)也會(huì)造成阻塞,10G帶寬會(huì)比1G帶寬的阻塞耗時(shí)少一些,而 1G 帶寬又會(huì)比 100M 帶寬的阻塞少一些。 通常情況下,我們把網(wǎng)絡(luò) IO 放在第三順位來考慮,然而有些人會(huì)在性能計(jì)算中忽略網(wǎng)絡(luò) IO 帶來的影響。

Mybatis引出的一系列問題-JDBC 的探究,mybaits,mybatis,oracle,數(shù)據(jù)庫
上圖是 PostgreSQL 的基準(zhǔn)性能測(cè)試數(shù)據(jù),從圖中我們可以看到,TPS 在連接數(shù)達(dá)到 50 時(shí)開始變緩。 回過頭來想下,Oracle 的性能測(cè)試中,測(cè)試人員們將連接數(shù)從 2048 降到了 96,實(shí)際上 96 還是太高了,除非你的服務(wù)器 CPU 核心數(shù)有 16 或 32。

下面公式由 PostgreSQL 提供,不過底層原理是不變的,它適用于市面上絕大部分?jǐn)?shù)據(jù)庫產(chǎn)品。 還有,你應(yīng)該模擬預(yù)期的訪問量,并通過下面的公式先設(shè)置一個(gè)偏合理的值,然后在實(shí)際的測(cè)試中,通過微調(diào),來尋找最合適的連接數(shù)大小。

連接數(shù) = ((核心數(shù) * 2) + 有效磁盤數(shù))

核心數(shù)不應(yīng)包含超線程(hyper thread),即使打開了超線程也是如此,如果熱點(diǎn)數(shù)據(jù)全被緩存了,那么有效磁盤數(shù)實(shí)際是0,隨著緩存命中率的下降,有效磁盤數(shù)也逐漸趨近于實(shí)際的磁盤數(shù)。 另外需要注意,這一公式作用于SSD 的效果如何,尚未明了。

好了,按照這個(gè)公式,如果說你的服務(wù)器 CPU 是 4核 i7 的,連接池大小應(yīng)該為 ((4*2)+1)=9。 取個(gè)整, 我們就設(shè)置為 10 吧。你這個(gè)行不行?。?0 也太小了吧!

你要是覺得不太行的話,可以跑個(gè)性能測(cè)試看看,我們可以保證,它能輕松支撐 3000 用戶以 6000 TPS 的速率并發(fā)執(zhí)行簡單查詢的場(chǎng)景。 你還可以將連接池大小超過 10,那時(shí),你會(huì)看到響應(yīng)時(shí)長開始增加,TPS 開始下降。

**結(jié)論:**你需要的是一個(gè)小連接池,和一個(gè)等待連接的線程隊(duì)列 ,假設(shè)說你有 10000 個(gè)并發(fā)訪問,而你設(shè)置了連接池大小為 10000,你怕是石樂志哦。 改成 1000,太高?改成 100?還是太多了。你僅僅需要一個(gè)大小為 10 數(shù)據(jù)庫連接池,然后讓剩下的業(yè)務(wù)線程都在隊(duì)列里等待就可以了。

**連接池中的連接數(shù)量大小應(yīng)該設(shè)置成:**數(shù)據(jù)庫能夠有效同時(shí)進(jìn)行的查詢?nèi)蝿?wù)數(shù)(通常情況下來說不會(huì)高于 2*CPU核心數(shù))。 你應(yīng)該經(jīng)常會(huì)看到一些用戶量不是很大的 web 應(yīng)用中,為應(yīng)付大約十來個(gè)的并發(fā),卻將數(shù)據(jù)庫連接池設(shè)置成 100, 200 的情況。請(qǐng)不要過度配置您的數(shù)據(jù)庫連接池的大小。

實(shí)際上,連接池的大小的設(shè)置還是要結(jié)合實(shí)際的業(yè)務(wù)場(chǎng)景來說事。 比如說,你的系統(tǒng)同時(shí)混合了長事務(wù)和短事務(wù),這時(shí),根據(jù)上面的公式來計(jì)算就很難辦了。正確的做法應(yīng)該是創(chuàng)建兩個(gè)連接池,一個(gè)服務(wù)于長事務(wù),一個(gè)服務(wù)于"實(shí)時(shí)"查詢,也就是短事務(wù)。 還有一種情況,比方說一個(gè)系統(tǒng)執(zhí)行一個(gè)任務(wù)隊(duì)列,業(yè)務(wù)上要求同一時(shí)間內(nèi)只允許執(zhí)行一定數(shù)量的任務(wù),這時(shí),我們就應(yīng)該讓并發(fā)任務(wù)數(shù)去適配連接池連接數(shù),而不是連接數(shù)大小去適配并發(fā)任務(wù)數(shù)。

4 數(shù)據(jù)庫連接池druid參數(shù)詳解

spring:
    datasource:
        druid:
            # 指定數(shù)據(jù)源類型為DruidDataSource
            type: com.alibaba.druid.pool.DruidDataSource
            # 數(shù)據(jù)庫連接URL
            url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false
            # 數(shù)據(jù)庫用戶名
            username: root
            # 數(shù)據(jù)庫密碼
            password: "xx123!@#"
            # 連接池初始化時(shí)創(chuàng)建的連接數(shù)
            initialSize: 5
            # 連接池中最大連接數(shù)
            maxActive: 50
            # 連接池中最小空閑連接數(shù)
            minIdle: 5
            # 連接池中最大空閑連接數(shù)
            maxIdle: 10
            # 獲取連接時(shí)的最大等待時(shí)間(毫秒)
            maxWait: 60000
            # 間隔多久檢測(cè)一次空閑連接(毫秒)
            timeBetweenEvictionRunsMillis: 60000
            # 連接池中連接最小空閑時(shí)間(毫秒)
            minEvictableIdleTimeMillis: 300000
            # 用于檢測(cè)連接是否有效的SQL語句
            validationQuery: SELECT 1
            # 是否開啟空閑連接的檢測(cè)
            testWhileIdle: true
            # 是否開啟連接的檢測(cè)功能,在獲取連接時(shí)檢測(cè)連接是否有效
            testOnBorrow: false
            # 是否開啟連接的檢測(cè)功能,在歸還連接時(shí)檢測(cè)連接是否有效
            testOnReturn: false
            # 是否緩存PreparedStatement對(duì)象
            poolPreparedStatements: true
            # 緩存PreparedStatement對(duì)象的最大數(shù)量
            maxPoolPreparedStatementPerConnectionSize: 20
            # 配置監(jiān)控統(tǒng)計(jì)用的filter,允許監(jiān)控統(tǒng)計(jì)
            filters: stat
            # 配置擴(kuò)展屬性,用于監(jiān)控統(tǒng)計(jì)分析SQL性能等
            connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000

1、type: 數(shù)據(jù)源類型,這里使用了Druid連接池的類型。 注意事項(xiàng):使用Druid連接池的時(shí)候需要添加Druid連接池的依賴

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>${druid.version}</version>
</dependency> 

2、url: 數(shù)據(jù)庫連接的URL。 注意事項(xiàng):需要根據(jù)實(shí)際情況修改URL。

3、username: 數(shù)據(jù)庫用戶名。

4、password: 數(shù)據(jù)庫密碼 ;包含一些特殊字符的時(shí)候需要加引號(hào)。

5、initialSize: 連接池初始化時(shí)創(chuàng)建的連接數(shù)。 需要根據(jù)實(shí)際情況設(shè)置連接數(shù)。連接池創(chuàng)建連接時(shí),會(huì)創(chuàng)建initialSize個(gè)連接,以確保應(yīng)用程序在啟動(dòng)時(shí)可以立即獲取到數(shù)據(jù)庫連接。

6、maxActive: 連接池中最大連接數(shù)。 需要根據(jù)實(shí)際情況設(shè)置最大連接數(shù)。如果連接池中連接數(shù)達(dá)到maxActive,則應(yīng)用程序獲取連接的請(qǐng)求將被阻塞,直到有連接被釋放。

7、minIdle: 連接池中最小空閑連接數(shù)。 需要根據(jù)實(shí)際情況設(shè)置最小空閑連接數(shù)。如果連接池中空閑連接數(shù)少于minIdle,連接池會(huì)創(chuàng)建新的連接以達(dá)到minIdle。

8、maxIdle: 連接池中最大空閑連接數(shù)。 需要根據(jù)實(shí)際情況設(shè)置最大空閑連接數(shù)。如果連接池中空閑連接數(shù)超過maxIdle,連接池會(huì)關(guān)閉多余的連接以避免占用過多的資源。

9、maxWait: 獲取連接時(shí)的最大等待時(shí)間。 需要根據(jù)實(shí)際情況設(shè)置最大等待時(shí)間。如果連接池中沒有可用連接且已經(jīng)達(dá)到最大連接數(shù),則應(yīng)用程序獲取連接的請(qǐng)求將被阻塞,最多等待maxWait毫秒。

10、timeBetweenEvictionRunsMillis: 間隔多久檢測(cè)一次空閑連接(毫秒)。 需要根據(jù)實(shí)際情況設(shè)置檢測(cè)間隔時(shí)間。連接池會(huì)定期檢查空閑連接的狀態(tài),如果空閑時(shí)間超過minEvictableIdleTimeMillis,則將連接關(guān)閉。

11、minEvictableIdleTimeMillis: 連接池中連接最小空閑時(shí)間(毫秒)。 需要根據(jù)實(shí)際情況設(shè)置最小空閑時(shí)間。連接池會(huì)定期檢查空閑連接的狀態(tài),如果空閑時(shí)間超過minEvictableIdleTimeMillis,則將連接關(guān)閉。

12、validationQuery: 用于檢測(cè)連接是否有效的SQL語句。 需要根據(jù)實(shí)際情況設(shè)置SQL語句。連接池會(huì)使用這個(gè)SQL語句來檢測(cè)連接是否有效。

13、testWhileIdle: 是否開啟空閑連接的檢測(cè)。 需要根據(jù)實(shí)際情況設(shè)置是否開啟空閑連接的檢測(cè)。如果開啟,連接池會(huì)定期檢查空閑連接的狀態(tài)。

14、testOnBorrow: 是否開啟連接的檢測(cè)功能, 在獲取連接時(shí)檢測(cè)連接是否有效。 需要根據(jù)實(shí)際情況設(shè)置是否開啟連接的檢測(cè)功能。如果開啟,連接池在獲取連接時(shí)會(huì)檢查連接是否有效。

15、testOnReturn: 是否開啟連接的檢測(cè)功能,在歸還連接時(shí)檢測(cè)連接是否有效。 需要根據(jù)實(shí)際情況設(shè)置是否開啟連接的檢測(cè)功能。如果開啟,連接池在歸還連接時(shí)會(huì)檢查連接是否有效。

16、poolPreparedStatements: 是否緩存PreparedStatement對(duì)象。 需要根據(jù)實(shí)際情況設(shè)置是否緩存PreparedStatement對(duì)象。如果開啟,連接池會(huì)緩存PreparedStatement對(duì)象以提高性能。

17、maxPoolPreparedStatementPerConnectionSize: 緩存PreparedStatement對(duì)象的最大數(shù)量。 需要根據(jù)實(shí)際情況設(shè)置緩存的最大數(shù)量。如果開啟了緩存PreparedStatement對(duì)象,連接池會(huì)限制每個(gè)連接緩存的最大數(shù)量。

maxPoolPreparedStatementPerConnectionSize是Druid連接池的一個(gè)配置項(xiàng),用于配置連接池中緩存的PreparedStatement的最大數(shù)量。 PreparedStatement是預(yù)編譯的SQL語句,可以提高SQL執(zhí)行的效率和安全性,避免SQL注入等安全問題。 在使用Druid連接池時(shí),當(dāng)開啟了緩存PreparedStatement功能時(shí),每個(gè)連接都會(huì)緩存一定數(shù)量的PreparedStatement對(duì)象,以便在需要執(zhí)行SQL語句時(shí)能夠快速獲取。

而maxPoolPreparedStatementPerConnectionSize就是用于配置每個(gè)連接中緩存的PreparedStatement的最大數(shù)量。 需要注意的是,緩存PreparedStatement雖然可以提高SQL執(zhí)行的效率,但同時(shí)也會(huì)占用一定的內(nèi)存資源。因此,需要根據(jù)實(shí)際情況進(jìn)行合理配置。 默認(rèn)情況下,該屬性的值為10。

在上面的配置中,maxPoolPreparedStatementPerConnectionSize: 20 ;表示將每個(gè)連接中緩存的PreparedStatement的最大數(shù)量設(shè)置為20個(gè)。

18、filters: 配置監(jiān)控統(tǒng)計(jì)用的filter,允許監(jiān)控統(tǒng)計(jì)。 如果要使用Druid的監(jiān)控功能,需要配置此項(xiàng)。stat表示使用Druid的監(jiān)控功能。

19、connectionProperties: 配置擴(kuò)展屬性,用于監(jiān)控統(tǒng)計(jì)分析SQL性能等。 druid.stat.mergeSql和druid.stat.slowSqlMillis是兩個(gè)與SQL監(jiān)控有關(guān)的屬性。

druid.stat.mergeSql用于配置是否合并SQL。當(dāng)該屬性設(shè)置為true時(shí),Druid會(huì)將相同的SQL語句合并為一條,以節(jié)省SQL統(tǒng)計(jì)的開銷和提高統(tǒng)計(jì)精度。 默認(rèn)情況下,該屬性的值為false。

druid.stat.slowSqlMillis用于配置SQL執(zhí)行的時(shí)間閾值,單位為毫秒。當(dāng)一條SQL執(zhí)行的時(shí)間超過該閾值時(shí),Druid會(huì)將該SQL記錄到慢SQL列表中,以便進(jìn)行分析和優(yōu)化。默認(rèn)情況下,該屬性的值為3000毫秒。 在上面的配置中,druid.stat.mergeSql=true表示啟用SQL合并功能, druid.stat.slowSqlMillis=5000表示將SQL執(zhí)行的時(shí)間閾值設(shè)置為5000毫秒。 這些屬性的具體含義和配置方法,可以參考Druid的官方文檔。文章來源地址http://www.zghlxwxcb.cn/news/detail-631053.html

到了這里,關(guān)于Mybatis引出的一系列問題-JDBC 的探究的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • MyBatis-Plus中LambdaQueryWrapper的探究

    MyBatis-Plus的條件構(gòu)造器LambdaQueryWrapper是開發(fā)中常用的工具,和普通的QueryWrapper不同的是,LambdaQueryWrappe 可以識(shí)別Lambda表達(dá)式,獲取Lambda表達(dá)式對(duì)應(yīng)的字段名稱,在使用上更方便,此外,當(dāng)對(duì)象的字段發(fā)生變更時(shí)也更安全。 我們知道,Lambda表達(dá)式本質(zhì)上是一個(gè)匿名內(nèi)部類,實(shí)現(xiàn)

    2024年01月16日
    瀏覽(19)
  • 案例分享-被*隊(duì)友的mybatis蠢哭的一天

    案例分享-被*隊(duì)友的mybatis蠢哭的一天

    昨晚加班的時(shí)候被隊(duì)友拉著看一個(gè)mybatis的問題,耗費(fèi)了我一個(gè)小時(shí)時(shí)間,最后差點(diǎn)沒被我打死,實(shí)在是覺得滑稽,今天回家寫下來跟大伙分享一下。 Invalid bound statement (not found),看到這個(gè)錯(cuò)我當(dāng)時(shí)就沒興趣了,我說你這不就是xml里沒寫xxxMapper.java方法對(duì)應(yīng)的語句嗎,這還有啥

    2024年02月07日
    瀏覽(23)
  • Failed to load driver class com.mysql.cj.jdbc.Driver異常-IntellIJ Idea-后端項(xiàng)目連接數(shù)據(jù)庫_添加MyBatis依賴配置問題

    Failed to load driver class com.mysql.cj.jdbc.Driver異常-IntellIJ Idea-后端項(xiàng)目連接數(shù)據(jù)庫_添加MyBatis依賴配置問題

    前言 :后端項(xiàng)目連接數(shù)據(jù)庫配置時(shí),添加了如下application.properties的數(shù)據(jù)庫連接配置 項(xiàng)目點(diǎn)擊運(yùn)行,就出現(xiàn)以下系列問題 這種情況通常是由于以下原因之—引起的: 1.沒有在項(xiàng)目中引入mysql-connectorjar包,或者引入的包版本與JDBC驅(qū)動(dòng)不匹配。解決方法:在項(xiàng)目pom.xml中添加相關(guān)依

    2024年02月05日
    瀏覽(95)
  • 【MyBatis學(xué)習(xí)】MyBatis操縱數(shù)據(jù)庫進(jìn)行查詢操作 ?MyBatis與JDBC想比怎么樣,趕快與我一起探索吧 ! ! !

    【MyBatis學(xué)習(xí)】MyBatis操縱數(shù)據(jù)庫進(jìn)行查詢操作 ?MyBatis與JDBC想比怎么樣,趕快與我一起探索吧 ! ! !

    前言: 大家好,我是 良辰丫 ,從今天開始我們就要進(jìn)入MyBatis的學(xué)習(xí)了,請(qǐng)君與我一起操縱數(shù)據(jù)庫,MyBatis到底是什么呢?我們慢慢往下瞧! ! !?????? ??個(gè)人主頁:良辰針不戳 ??所屬專欄:javaEE進(jìn)階篇之框架學(xué)習(xí) ??勵(lì)志語句:生活也許會(huì)讓我們遍體鱗傷,但最終這些傷口會(huì)成為我

    2024年02月09日
    瀏覽(17)
  • Java 用jdbc查詢 比用mybatis查詢更快嗎?

    Java 用jdbc查詢 比用mybatis查詢更快嗎? 在Java中進(jìn)行數(shù)據(jù)庫查詢時(shí),開發(fā)者常常面臨選擇使用JDBC還是MyBatis的抉擇。本文將深入探討這兩者之間的性能差異,以及在不同場(chǎng)景下的優(yōu)劣勢(shì)。通過詳細(xì)的比較和分析,希望讀者能夠更好地理解在實(shí)際項(xiàng)目中如何做出明智的選擇。 引言

    2024年01月18日
    瀏覽(13)
  • SpringBoot原理分析 | Spring Data整合:JDBC、Druid、Mybatis

    SpringBoot原理分析 | Spring Data整合:JDBC、Druid、Mybatis

    ??wei_shuo的個(gè)人主頁 ??wei_shuo的學(xué)習(xí)社區(qū) ??Hello World ! Spring Data是一個(gè)用于簡化數(shù)據(jù)庫訪問和操作的開源框架,為開發(fā)人員提供了一種通用的方式來處理不同類型的數(shù)據(jù)存儲(chǔ),例如關(guān)系型數(shù)據(jù)庫(如MySQL、PostgreSQL、Oracle)和非關(guān)系型數(shù)據(jù)庫(如MongoDB、Cassandra、Redis)等。

    2024年02月12日
    瀏覽(47)
  • MSVS C# Matlab的混合編程系列1 - 看似簡單的問題引出

    MSVS C# Matlab的混合編程系列1 - 看似簡單的問題引出

    問題提出,如何把Matlab(本文簡稱MT)的算法集成到Visual Studio(本文簡稱VS)里面運(yùn)行? 本文,通過編制一個(gè)MT中最簡單的加法函數(shù),我們把他做成 MSVS C#能夠使用的動(dòng)態(tài)庫,說明了MSVS C# 和 MT集成的最小,然而,最簡潔清晰的處理方法和過程。? 1 VS2019 2 C# .Net 應(yīng)用環(huán)境 3 MT2019 指的

    2024年01月21日
    瀏覽(4)
  • MyBatis動(dòng)態(tài)sql之批量修改、批量新增(使用foreach標(biāo)簽的一條sql語句解決)

    ????????批量新增和批量修改在業(yè)務(wù)中是很常見的,一條sql訪問數(shù)據(jù)庫和通過代碼循環(huán)體中循環(huán)訪問數(shù)據(jù)庫做單個(gè)數(shù)據(jù)新增修改相比較下:一條sql訪問數(shù)據(jù)庫性能上明顯提升,代碼且簡潔明了 1、Mapper.java中 說明: 參數(shù)是list ?2、Mapper.xml中 說明: 通過trim標(biāo)簽拼接前后綴和

    2024年02月10日
    瀏覽(22)
  • SpringBoot+Sharding-jdbc+mybatis-plus實(shí)現(xiàn)水平分表

    這塊我就不演示了

    2024年02月12日
    瀏覽(19)
  • Mybatis-Plus集成Sharding-JDBC與Flyway實(shí)現(xiàn)多租戶分庫分表

    Mybatis-Plus集成Sharding-JDBC與Flyway實(shí)現(xiàn)多租戶分庫分表

    公司產(chǎn)品部收到了一些重要客戶的需求,他們希望能夠依賴獨(dú)立的數(shù)據(jù)庫存儲(chǔ)來支持他們的業(yè)務(wù)數(shù)據(jù)。與此同時(shí),仍有許多中小客戶,可以繼續(xù)使用公共庫以滿足其需求。技術(shù)實(shí)現(xiàn)方面,此前持久層框架使用的Mybatis-plus,部分業(yè)務(wù)場(chǎng)景使用到了Sharding-JDBC用于分表,另外,我們

    2024年02月05日
    瀏覽(24)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包