資料庫自動重連

pincharensheng發表於2016-12-22

方式一(c3p0):

1、引入c3p0 maven依賴

<dependency>  
     <groupId>c3p0</groupId>  
     <artifactId>c3p0</artifactId>  
     <version>0.9.1.2</version>  
</dependency>


2、配置mybatis

mybatis-config.xml

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">

<property name="properties" ref="dataSourceProperties"/>

<property name="driverClass" value="#{dataSourceProps['jdbc.driverClass']}" />  

<property name="jdbcUrl" value="#{dataSourceProps['jdbc.url']}" />  
<property name="user" value="#{dataSourceProps['jdbc.username']}" />
<property name="password" value="#{dataSourceProps['jdbc.password']}" />
<!--初始化時獲取三個連線,取值應在minPoolSize與maxPoolSize之間。Default: 3 -->   
<property name="initialPoolSize" value="5" />  
<property name="minPoolSize" value="5" />  
<property name="maxPoolSize" value="20" />  
<!--最大空閒時間,60秒內未使用則連線被丟棄。若為0則永不丟棄。Default: 0 -->   
<property name="maxIdleTime" value="60" />  
<!--每30秒檢查所有連線池中的空閒連線。Default: 0 -->   
<property name="idleConnectionTestPeriod" value="30" />
<property name="preferredTestQuery" value="#{dataSourceProps['jdbc.validationQuery']}" />  

<!-- JDBC的標準引數,用以控制資料來源內載入的PreparedStatements數量。但由於預快取的statements   
            屬於單個connection而不是整個連線池。所以設定這個引數需要考慮到多方面的因素。   
            如果maxStatements與maxStatementsPerConnection均為0,則快取被關閉。Default: 0-->   
<property name="maxStatements" value="0" />
<!--如果設為true那麼在取得連線的同時將校驗連線的有效性。Default: false-->
    <property name="testConnectionOnCheckin" value="true" />

</bean>

<!--密碼加密-->

<bean id="dataSourceProperties" class="com.test.common.util.PropertiesEncryptFactoryBean">  
        <property name="properties">  
            <props>  
                <prop key="password">#{dataSourceProps['jdbc.password']}</prop>  
            </props>  
        </property>  
    </bean>  

3、PropertiesEncryptFactoryBean程式碼

public class PropertiesEncryptFactoryBean implements FactoryBean {  
    
    private Properties properties;

    public Properties getProperties() {
        return properties;
    }

    public void setProperties(Properties inProperties) {
        this.properties = inProperties;
        String originalPassword = properties.getProperty("password");  
        if (originalPassword != null){
            try {
                Crypto crypto = new Crypto();
                String newPassword = crypto.decrypt(originalPassword);
                properties.put("password", newPassword);  
            } catch (Exception e) {
                e.printStackTrace();
            }
        }  
    }

    @Override
    public Object getObject() throws Exception {
        return getProperties();
    }

    @Override
    public Class getObjectType() {
        return java.util.Properties.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
    
}


4、jdbc.properties配置

jdbc.driverClass=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@192.168.71.120:1521:orcl
jdbc.username=test
jdbc.password=4f145de38  --加密後的密碼
jdbc.validationQuery=SELECT sysdate FROM dual


方式二(JNDI):

jboss下面配置JNDI方式:

加上以下標註紅線的內容就是加上自動重連功能! 在配置連線池的地方是oracle的配置方法

<?xml version="1.0" encoding="UTF-8"?>
<datasources>
  <local-tx-datasource>
      <jndi-name>flhis</jndi-name>
      <connection-url>jdbc:oracle:thin:@192.168.71.120:1521:orcl</connection-url>
      <driver-class>oracle.jdbc.driver.OracleDriver</driver-class>
      <user-name>test</user-name>
      <password>test</password>
       <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name>

       <background-validation>true</background-validation>
      <background-validation-minutes>1</background-validation-minutes>
      <check-valid-connection-sql>SELECT sysdate FROM dual</check-valid-connection-sql>

      <min-pool-size>5</min-pool-size>
      <max-pool-size>20</max-pool-size>
      <idle-timeout-minutes>0</idle-timeout-minutes>
      <track-statements/>
      <prepared-statement-cache-size>32</prepared-statement-cache-size>
   </local-tx-datasource>
</datasources>

jboss配置參考:https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Web_Platform/5/html/Administration_And_Configuration_Guide/ch12s02.html




c3p0配置參考:
1.基本配置項
acquireIncrement
default : 3
連線池在無空閒連線可用時一次性建立的新資料庫連線數

initialPoolSize
default : 3
連線池初始化時建立的連線數

maxPoolSize
default : 15
連線池中擁有的最大連線數,如果獲得新連線時會使連線總數超過這個值則不會再獲取新連線,而是等待
其他連線釋放,所以這個值有可能會設計地很大

maxIdleTime
default : 0 單位 s
連線的最大空閒時間,如果超過這個時間,某個資料庫連線還沒有被使用,則會斷開掉這個連線
如果為0,則永遠不會斷開連線

minPoolSize
default : 3
連線池保持的最小連線數,後面的maxIdleTimeExcessConnections跟這個配合使用來減輕連線池的負載


2.管理連線池的大小和連線的生存時間
maxConnectionAge
default : 0 單位 s
配置連線的生存時間,超過這個時間的連線將由連線池自動斷開丟棄掉。當然正在使用的連線不會馬上斷開,而是等待
它close再斷開。配置為0的時候則不會對連線的生存時間進行限制。

maxIdleTimeExcessConnections
default : 0 單位 s
這個配置主要是為了減輕連線池的負載,比如連線池中連線數因為某次資料訪問高峰導致建立了很多資料連線
但是後面的時間段需要的資料庫連線數很少,則此時連線池完全沒有必要維護那麼多的連線,所以有必要將
斷開丟棄掉一些連線來減輕負載,必須小於maxIdleTime。配置不為0,則會將連線池中的連線數量保持到minPoolSize。
為0則不處理。
maxIdleTime也可以歸屬到這一類,前面已經寫出來了。


3.配置連線測試:因為連線池中的資料庫連線很有可能是維持數小時的連線,很有可能因為資料庫伺服器的問題,網路問題等導致實際連線已經無效,但是連線池裡面的連線還是有效的,如果此時獲得連線肯定會發生異常,所以有必要通過測試連線來確認連線的有效性。
下面的前三項用來配置如何對連線進行測試,後三項配置對連線進行測試的時機。

automaticTestTable
default : null
用來配置測試連線的一種方式。配置一個表名,連線池根據這個表名建立一個空表,
並且用自己的測試sql語句在這個空表上測試資料庫連線
這個表只能由c3p0來使用,使用者不能操作,同時使用者配置的preferredTestQuery 將會被忽略。

preferredTestQuery
default : null
用來配置測試連線的另一種方式。與上面的automaticTestTable二者只能選一。
如果要用它測試連線,千萬不要設為null,否則測試過程會很耗時,同時要保證sql語句中的表在資料庫中一定存在。

connectionTesterClassName
default :  com.mchange.v2.c3p0.impl.DefaultConnectionTester
連線池用來支援automaticTestTable和preferredTestQuery測試的類,必須是全類名,就像預設的那樣,
可以通過實現UnifiedConnectionTester介面或者繼承AbstractConnectionTester來定製自己的測試方法
idleConnectionTestPeriod
default : 0
用來配置測試空閒連線的間隔時間。測試方式還是上面的兩種之一,可以用來解決MySQL8小時斷開連線的問題。因為它
保證連線池會每隔一定時間對空閒連線進行一次測試,從而保證有效的空閒連線能每隔一定時間訪問一次資料庫,將於MySQL
8小時無會話的狀態打破。為0則不測試。

testConnectionOnCheckin
default : false
如果為true,則在close的時候測試連線的有效性。為了提高測試效能,可以與idleConnectionTestPeriod搭配使用,
配置preferredTestQuery或automaticTestTable也可以加快測試速度。
testConnectionOnCheckout
default : false
效能消耗大。如果為true,在每次getConnection的時候都會測試,為了提高效能,
可以與idleConnectionTestPeriod搭配使用,
配置preferredTestQuery或automaticTestTable也可以加快測試速度。


4.配置PreparedStatement快取
maxStatements
default : 0
連線池為資料來源快取的PreparedStatement的總數。由於PreparedStatement屬於單個Connection,所以
這個數量應該根據應用中平均連線數乘以每個連線的平均PreparedStatement來計算。為0的時候不快取,
同時maxStatementsPerConnection的配置無效。
maxStatementsPerConnection
default : 0
連線池為資料來源單個Connection快取的PreparedStatement數,這個配置比maxStatements更有意義,因為
它快取的服務物件是單個資料連線,如果設定的好,肯定是可以提高效能的。為0的時候不快取。


5.重連相關配置
acquireRetryAttempts
default : 30
連線池在獲得新連線失敗時重試的次數,如果小於等於0則無限重試直至連線獲得成功
acquireRetryDelay
default : 1000 單位ms
連線池在獲得新連線時的間隔時間
breakAfterAcquireFailure
default : false
如果為true,則當連線獲取失敗時自動關閉資料來源,除非重新啟動應用程式。所以一般不用。
個人覺得上述三個沒有更改的必要,但可以將acquireRetryDelay配置地更短一些


6.定製管理Connection的生命週期
connectionCustomizerClassName
default : null
用來定製Connection的管理,比如在Connection acquire 的時候設定Connection的隔離級別,或者在
Connection丟棄的時候進行資源關閉,就可以通過繼承一個AbstractConnectionCustomizer來實現相關
方法,配置的時候使用全類名。有點類似監聽器的作用。
例如:
import java.sql.Connection;
import com.mchange.v2.c3p0.AbstractConnectionCustomizer;
public class ConnectionCustomizer extends AbstractConnectionCustomizer{
    @Override
    public void onAcquire(Connection c, String parentDataSourceIdentityToken)
            throws Exception {
        System.out.println("acquire : " + c);
    }
    @Override
    public void onCheckIn(Connection c, String parentDataSourceIdentityToken)
            throws Exception {
        System.out.println("checkin : " + c);
    }
    @Override
    public void onCheckOut(Connection c, String parentDataSourceIdentityToken)
            throws Exception {
       System.out.println("checkout : " + c);
    }
    @Override
    public void onDestroy(Connection c, String parentDataSourceIdentityToken)
            throws Exception {
        System.out.println("destroy : " + c);
    }
}
<property name="connectionCustomizerClassName">liuyun.zhuge.db.ConnectionCustomizer</property>


7.配置未提交的事務處理
autoCommitOnClose
default : false
連線池在回收資料庫連線時是否自動提交事務
如果為false,則會回滾未提交的事務
如果為true,則會自動提交事務
forceIgnoreUnresolvedTransactions
default : false
這個配置強烈不建議為true。
一般來說事務當然由自己關閉了,為什麼要讓連線池來處理這種不細心問題呢?


8.配置debug和回收Connection
unreturnedConnectionTimeout
default : 0 單位 s
為0的時候要求所有的Connection在應用程式中必須關閉。如果不為0,則強制在設定的時間到達後回收
Connection,所以必須小心設定,保證在回收之前所有資料庫操作都能夠完成。這種限制減少Connection未關閉
情況的不是很適用。為0不對connection進行回收,即使它並沒有關閉。
debugUnreturnedConnectionStackTraces
default : false
如果為true並且unreturnedConnectionTimeout設為大於0的值,當所有被getConnection出去的連線
unreturnedConnectionTimeout時間到的時候,就會列印出堆疊資訊。只能在debug模式下適用,因為
列印堆疊資訊會減慢getConnection的速度
同第七項一樣的,連線用完當然得close了,不要通過unreturnedConnectionTimeout讓連線池來回收未關閉的連線。


9.其他配置項:因為有些配置項幾乎沒有自己配置的必要,使用預設值就好,所以沒有再寫出來
checkoutTimeout
default : 0
配置當連線池所有連線用完時應用程式getConnection的等待時間。為0則無限等待直至有其他連線釋放
或者建立新的連線,不為0則當時間到的時候如果仍沒有獲得連線,則會丟擲SQLException

相關文章