1. 程式人生 > 實用技巧 >mybatis連線池

mybatis連線池

連線池

在 Mybatis 中,資料來源 dataSource 共有三類,分別是:
UNPOOLED : 不使用連線池的資料來源。採用傳統的 javax.sql.DataSource 規範中的連線池,Mybatis 中有針對規範的實現
POOLED : 使用連線池的資料來源。採用池的思想
JNDI : 使用 JNDI 實現的資料來源,採用伺服器提供的 JNDI 技術實現,來獲取 DataSource 物件,不同的伺服器所能拿到的 DataSource 是不一樣的。(如果不是web或者maven的war工程,是不能使用的,tomcat-dbcp連線池:因為需要相應的程式碼需要在伺服器端才能啟動,連線池連線的資料來源是部署在伺服器上的,如tomcat你可以在servlet或者jsp(最終還是會轉換成servlet)上進行sqlsession的建立才能在jndi上getConnection到相應的connection,通過瀏覽器或客戶端對伺服器的訪問呼叫了伺服器上部署的有相應需要連線資料庫的方法,才能呼叫伺服器連線的資料庫源

連線池和執行緒池:

連線池:(降低物理連線損耗)
1、連線池是面向資料庫連線的
2、連線池是為了優化資料庫連線資源
3、連線池有點類似在客戶端做優化

資料庫連線是一項有限的昂貴資源,一個數據庫連線物件均對應一個物理資料庫連線,每次操作都開啟一個物理連線,使用完都關閉連線,這樣造成系統的效能低下。 資料庫連線池的解決方案是在應用程式啟動時建立足夠的資料庫連線,並將這些連線組成一個連線池,由應用程式動態地對池中的連線進行申請、使用和釋放。對於多於連線池中連線數的併發請求,應該在請求佇列中排隊等待。並且應用程式可以根據池中連線的使用率,動態增加或減少池中的連線數

執行緒池:(降低執行緒建立銷燬損耗)
1.、執行緒池是面向後臺程式的
2、執行緒池是是為了提高記憶體和CPU效率
3、執行緒池有點類似於在服務端做優化

執行緒池是一次性建立一定數量的執行緒(應該可以配置初始執行緒數量的),當用請求過來不用去建立新的執行緒,直接使用已建立的執行緒,使用後又放回到執行緒池中。
避免了頻繁建立執行緒,及銷燬執行緒的系統開銷,提高是記憶體和CPU效率。

相同點:
都是事先準備好資源,避免頻繁建立和銷燬的代價。

擴充套件:
物件池:
物件池技術基本原理的核心有兩點:快取和共享,即對於那些被頻繁使用的物件,在使用完後,不立即將它們釋放,而是將它們快取起來,以供後續的應用程式重複使用,從而減少建立物件和釋放物件的次數,進而改善應用程式的效能。事實上,由於物件池技術將物件限制在一定的數量,也有效地減少了應用程式記憶體上的開銷。

對於兩者是否有聯絡:

  1. 首先,每個連線要啟動,都需要依賴於一個執行緒的呼叫,否則,即使連線在連線池裡,沒有斷開連線,也無法做出行為
  2. 當執行緒使用完時,會將連線與執行緒解綁交還於連線池
  3. 一般會是多個連線併發執行,即需要多個執行緒,因此前面也有執行緒池的管理
  4. 每個連線都是執行緒安全的,用synchronized鎖住
while(conn == null) {
    synchronized(this.state) {
        PoolState var10000;
        if (!this.state.idleConnections.isEmpty()) {
            conn = (PooledConnection)this.state.idleConnections.remove(0);
            if (log.isDebugEnabled()) {
                log.debug("Checked out connection " + conn.getRealHashCode() + " from pool.");
            }
        } else if (this.state.activeConnections.size() < this.poolMaximumActiveConnections) {
            conn = new PooledConnection(this.dataSource.getConnection(), this);
            if (log.isDebugEnabled()) {
                log.debug("Created connection " + conn.getRealHashCode() + ".");
            }
        } else {
            PooledConnection oldestActiveConnection = (PooledConnection)this.state.activeConnections.get(0);
            long longestCheckoutTime = oldestActiveConnection.getCheckoutTime();
            if (longestCheckoutTime > (long)this.poolMaximumCheckoutTime) {
                ++this.state.claimedOverdueConnectionCount;
                var10000 = this.state;
                var10000.accumulatedCheckoutTimeOfOverdueConnections += longestCheckoutTime;
                var10000 = this.state;
                var10000.accumulatedCheckoutTime += longestCheckoutTime;
                this.state.activeConnections.remove(oldestActiveConnection);
                if (!oldestActiveConnection.getRealConnection().getAutoCommit()) {
                    try {
                        oldestActiveConnection.getRealConnection().rollback();
                    } catch (SQLException var16) {
                        log.debug("Bad connection. Could not roll back");
                    }
                }

                conn = new PooledConnection(oldestActiveConnection.getRealConnection(), this);
                conn.setCreatedTimestamp(oldestActiveConnection.getCreatedTimestamp());
                conn.setLastUsedTimestamp(oldestActiveConnection.getLastUsedTimestamp());
                oldestActiveConnection.invalidate();
                if (log.isDebugEnabled()) {
                    log.debug("Claimed overdue connection " + conn.getRealHashCode() + ".");
                }
            } else {
                try {
                    if (!countedWait) {
                        ++this.state.hadToWaitCount;
                        countedWait = true;
                    }

                    if (log.isDebugEnabled()) {
                        log.debug("Waiting as long as " + this.poolTimeToWait + " milliseconds for connection.");
                    }

                    long wt = System.currentTimeMillis();
                    this.state.wait((long)this.poolTimeToWait);
                    var10000 = this.state;
                    var10000.accumulatedWaitTime += System.currentTimeMillis() - wt;
                } catch (InterruptedException var17) {
                    break;
                }
            }
        }
  • 如果想要修改 Mybatis 使用的資料來源,那麼就可以在 Mybatis 配置檔案中修改:(這裡 type 屬性的取值就是為POOLED、UNPOOLED、JNDI 。)
<!-- 配置資料來源(連線池) -->
<dataSource type="POOLED">
    <property name="driver" value="${jdbc.driver}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</dataSource>

檢視 POOLED 的實現 PooledDataSource ,可以看出獲取連線時採用了池的思想,大概流程如下圖(只是一個簡單介紹,不全面)

檢視 UNPOOLED 的實現 UnpooledDataSource ,可以看出每次獲取連線時都會註冊驅動並建立新連線,大概流程如下圖(只是一個簡單介紹,不全面)