文章中若附原文鏈接,那部分內容對你有所幫助,請給原作者先點贊!
文章中若附原文鏈接,那部分內容對你有所幫助,請給原作者先點贊!
文章中若附原文鏈接,那部分內容對你有所幫助,請給原作者先點贊!
連接池
在 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效率。相同點:
都是事先准備好資源,避免頻繁創建和銷毀的代價。擴展:
對象池:
對象池技術基本原理的核心有兩點:緩存和共享,即對於那些被頻繁使用的對象,在使用完后,不立即將它們釋放,而是將它們緩存起來,以供后續的應用程序重復使用,從而減少創建對象和釋放對象的次數,進而改善應用程序的性能。事實上,由於對象池技術將對象限制在一定的數量,也有效地減少了應用程序內存上的開銷。對於兩者是否有聯系:
- 首先,每個連接要啟動,都需要依賴於一個線程的調用,否則,即使連接在連接池里,沒有斷開連接,也無法做出行為
- 當線程使用完時,會將連接與線程解綁交還於連接池
- 一般會是多個連接並發執行,即需要多個線程,因此前面也有線程池的管理
- 每個連接都是線程安全的,用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
,可以看出每次獲取連接時都會注冊驅動並創建新連接,大概流程如下圖(只是一個簡單介紹,不全面)
sqlsession、transaction、connection、sql語句的關系在下一篇文章中
https://www.cnblogs.com/eternal-heathens/p/13366799.html