概述
在這里所謂的數據庫連接是指通過網絡協議與數據庫服務之間建立的TCP連接。通常,與數據庫服務進行通信的網絡協議無需由應用程序本身實現,原因有三:
1.實現復雜度大,需要充分理解和掌握相應的通信協議。
2.代碼難以復用,每個應用程序都需要獨立實現一套對應的網絡協議(不同公司之間,同一公司的不同技術棧之間難以復用實現相同協議的代碼)
3.性能難以保證,不同的網絡協議實現可能存在巨大的性能差距
正因為如此,所以現實的實現方式是:
首先,定義網絡協議標準,這樣只要支持這個標準協議的數據庫就可以使用相應的客戶端與之通信。
其次,將實現這個標準協議的客戶端獨立為一個通信庫,這樣只需要在應用程序中使用這個通信組件庫就可以方便地實現與數據庫進行交互。
通常,我們將實現了網絡協議的通信庫稱之為數據庫驅動程序。當然,對于不同的編程語言,需要對應編寫相應的數據庫驅動
實現。以與關系型數據庫通信為例,在Java中實現的驅動程序為JDBC,Python中的驅動程序為MySQLdb。
由于通過TCP與數據庫建立網絡連接的代價非常高昂,而且耗時(TCP建立連接需要“三次握手”,斷開連接需要“四次握手”)。所以在實踐中通常不直接單獨使用連接進行數據庫操作,而是使用連接池的方式,這主要是處于以下兩方面的考慮:
應用程序本身需要更低的響應時間,如果每次數據庫操作都需要經過“建立連接->通信(增刪改查)->斷開連接”這個過程,那么勢必會導致響應延時的增加。
避免服務器資源被耗盡,隨著業務量的增大,對應的數據庫操作必然會隨之增加,如果對客戶端的連接數不加以控制,可能會導致數據庫服務器的CPU和內存資源被大量的網絡連接快速耗盡,這樣將導致服務不可用。
在Java中使用得比較流行的數據庫連接池主要有:DBCP,c3p0,druid。
另外,不論使用什么連接池,低層都是使用JDBC連接,即:在應用程序中都需要加載JDBC驅動程序。
DBCP
https://commons.apache.org/proper/commons-dbcp/index.html
DBCP是Apache下獨立的數據庫連接池組件,在Tomcat中使用的連接池組件就是DBCP,支持JDBC3,JDBC4。關于更多JDBC版本信息,詳見:https://en.wikipedia.org/wiki/Java_Database_Connectivity。
c3p0
http://www.mchange.com/projects/c3p0/
使用c3p0有多種方式,如:既可以直接使用API方式配置c3p0,也可以通過文件的方式進行配置,配置文件有2種形式:properties或xml文件。
<dependencies> <!-- JDBC驅動 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.42</version> </dependency> <!-- c3p0連接池 --> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.5.2</version> </dependency> <!-- 日志組件 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.25</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> </dependency> </dependencies>
1.使用Java API方式配置c3p0
ComboPooledDataSource cpds = new ComboPooledDataSource(); cpds.setDriverClass( "com.mysql.jdbc.Driver" ); //loads the jdbc driver cpds.setJdbcUrl("jdbc:mysql://host:port/db"); cpds.setUser("username"); cpds.setPassword("password"); cpds.setMinPoolSize(5); cpds.setMaxPoolSize(20); cpds.setAcquireIncrement(5); // 直接從連接池中獲取連接 Connection conn = cpds.getConnection(); query(conn); // 關閉連接池 // cpds.close();
2.使用文件方式配置c3p0
2.1 使用c3p0.properties文件進行配置
需要在classpath路徑下添加配置文件:c3p0.properties,內容如下:
c3p0.driverClass=com.mysql.jdbc.Driver c3p0.jdbcUrl=jdbc:mysql://host:port/db c3p0.user=root c3p0.password= c3p0.minPoolSize=5 c3p0.maxPoolSize=20 c3p0.acquireIncrement=5
在應用程序中只需要直接創建ComboPooledDataSource對象即可(c3p0會自動從classpath加載c3p0.properties中的配置信息):
ComboPooledDataSource cpds = new ComboPooledDataSource(); Connection conn = cpds.getConnection(); query(conn); cpds.close();
注意: 使用c3p0.properties作為配置文件時,每個參數的name前綴必須是“c3p0”,如:“c3p0.driverClass=com.mysql.jdbc.Driver”。
2.2 使用c3p0-config.xml文件進行配置
使用這種方式會比使用c3p0.properties更加高級,支持配置多個數據源,同樣需要在classpath路徑下添加文件:c3p0-config.xml。
<c3p0-config> <!-- 默認數據源 --> <default-config> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://host:port/db</property> <property name="user">username</property> <property name="password">password</property> <property name="minPoolSize">5</property> <property name="maxPoolSize">20</property> <property name="acquireIncrement">5</property> </default-config> <!-- 定義帶名稱的數據源 --> <named-config name="myDataSource"> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/test_jdbc</property> <property name="user">root</property> <property name="password"></property> <property name="minPoolSize">5</property> <property name="maxPoolSize">20</property> <property name="acquireIncrement">5</property> </named-config> </c3p0-config>
// 使用默認數據源 // ComboPooledDataSource cpds = new ComboPooledDataSource(); // 使用指定名稱的數據源 ComboPooledDataSource cpds = new ComboPooledDataSource("myDataSource"); Connection conn = cpds.getConnection(); query(conn); cpds.close();
3.c3p0常用配置
<c3p0-config> <default-config> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://host:port/db</property> <property name="user">username</property> <property name="password">password</property> <!-- 連接池初始化時創建的連接數,默認值: 3 --> <property name="initialPoolSize">3</property> <!-- 連接池保持的最小連接數,默認值: 3 --> <property name="minPoolSize">3</property> <!-- 連接池中擁有的最大連接數,如果獲得新連接時會使連接總數超過這個值則不會再獲取新連接,而是等待其他連接釋放。 --> <property name="maxPoolSize">15</property> <!-- 連接池在無空閑連接可用時一次性創建的新數據庫連接數,默認值: 3 --> <property name="acquireIncrement">3</property> <!-- 連接的最大空閑時間,如果超過這個時間,某個數據庫連接還沒有被使用,則會斷開掉這個連接。為0,則永遠不會斷開連接。默認值: 0,單位: 秒 --> <property name="maxIdleTime">0</property> <!-- 連接測試語句 --> <property name="preferredTestQuery">select 1</property> <!-- 用來配置測試空閑連接的間隔時間??梢杂脕斫鉀QMySQL 8小時斷開連接的問題。因為它保證連接池會每隔一定時間對空閑連接進行一次測試,從而保證有效的空閑連接能每隔一定時間訪問一次數據庫,將MySQL8小時無會話的狀態打破。為0則不測試。默認值:0,單位: 秒 --> <property name="idleConnectionTestPeriod">30</property> <!-- 連接池在獲得新連接失敗時重試的次數,如果小于等于0則無限重試直至連接獲得成功。默認值: 30 --> <property name="acquireRetryAttempts">30</property> <!-- 連接池在獲得新連接時的間隔時間,默認值: 1000,單位: 毫秒 --> <property name="acquireRetryDelay">1000</property> </default-config> </c3p0-config>
druid
https://github.com/alibaba/druid
阿里開源的druid不單純是一個連接池,還添加了監控功能,目前已經是非常受推崇的連接池組件,詳細配置參數請參考官網。
當然,還存在一些其他的數據庫連接池實現,例如:Tomcat自己就實現了一個連接池組件,根據官方的說法,這個連接池正是為了在Tomcat中替換DBCP,詳見:https://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。