国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發(fā)設(shè)計 > 正文

應知道的數(shù)據(jù)庫連接池DBCP配置及JDBC超時設(shè)置

2019-11-08 20:31:51
字體:
供稿:網(wǎng)友

應知道的數(shù)據(jù)庫連接池DBCP配置及JDBC超時設(shè)置

2016-06-15 張開濤 開濤的博客

 

2014年618前夕的某個晚上的某個系統(tǒng)的sql執(zhí)行時報錯了:

<!--添加同步數(shù)據(jù)--><insert id="insert" parameterClass="order">  INSERT INTO aa(ID,ORDERID,CREATEDATE)  VALUES  (seq.Nextval,#orderId#,#createDate#)  <selectKey resultClass="java.lang.Long">    SELECT seq.CURRVAL FROM DUAL  </selectKey></insert>

會拋出800多條如下錯誤

Caused by: java.sql.SQLException: ORA-01013: 用戶請求取消當前的操作at Oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)at oracle.jdbc.driver.T4CTTIoer.PRocessError(T4CTTIoer.java:331)at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:288)at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:745)at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:219)at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:970)

 

原因是sql執(zhí)行時間太長,jdbc驅(qū)動主動去取消了操作。

 

建議:

1、看一下該sql的平均執(zhí)行時間,對該sql設(shè)置一個超時時間。(執(zhí)行時間太長會對占用著連接,造成其他人拿不到連接)

2、找DBA咨詢下有沒有辦法優(yōu)化下該sql,比如能不能并行插入?;蛘吣懿荒茏龇謪^(qū)。

 

1、數(shù)據(jù)源配置

如果使用apache dbcp時,且可能遇到連接數(shù)瓶頸時,可以調(diào)整如下配置:

 

<!—建議以下值盡量一樣,沒必要頻繁的過期空閑連接(除非比如連接池資源緊缺,可以考慮) --><property name="maxIdle" value="80" /><property name="minIdle" value="80" /><property name="initialSize" value="80"/><property name="maxActive" value="80" />

 

<!—這個是等待獲取連接池連接時間,也不要太大,比如設(shè)置在500毫秒 --><property name="maxWait" value="500" />

<!-- 移除無引用連接(那些沒有close的連接)此處設(shè)置為false,需要保證程序中連接一定釋放 -->

<property name="removeAbandoned" value="false"></property><property name="removeAbandonedTimeout" value="300000"></property><!-- 一個連接空閑多久從池中移除,此處不做判斷--><property name="minEvictableIdleTimeMillis" value="-1" /><!-- 過期時循環(huán)測試多少次(0 就相當于關(guān)閉定時器) --><property name="numTestsPerEvictionRun" value="0" /><!-- expire connection 定時器周期 --><property name="timeBetweenEvictionRunsMillis" value="120000" />

<!-- 當連接空閑時是否測試,即保持連接一直存活,配合expire connection 定時器使用 -->

<property name="testWhileIdle" value="false"></property>

 

如果是MySQL庫,可能存在8小時問題,可以考慮開啟過期定時器(numTestsPerEvictionRun=1),定期過期一下連接,timeBetweenEvictionRunsMillis時間可以設(shè)置在8小時左右.

 

另外可以通過如下配置來配置socket連接/讀超時:

<property name="connectionProperties"

value="oracle.net.CONNECT_TIMEOUT=2000;oracle.jdbc.ReadTimeout=2000"></property>

(此處的連接和讀取超時時間,請根據(jù)自己業(yè)務(wù)來考慮大小)

 

更多配置可參考http://www.importnew.com/2466.html

 

2、ibatis配置

**項目使用的是ibatis-sqlmap-2.3.4.726.jar版本,而從2.3.1起:

o Removed maxTransactions, maxRequests, maxsessions from configuration, all are now controlled by the resource providers。(即已經(jīng)移除了maxTransactions, maxRequests, maxSessions配置)

  

因此我們只需要如下配置:

<settings cacheModelsEnabled="false" enhancementEnabled="true"

lazyLoadingEnabled="false" errorTracingEnabled="true" maxRequests="32"

defaultStatementTimeout="2"/>

 

defaultStatementTimeout單位是秒;根據(jù)業(yè)務(wù)配置。

  

如果想只設(shè)置某個Statement的超時時間,可以考慮:<insert ……timeout="2">

 

之前線上報如下錯誤,原因就是statement執(zhí)行超時了。

Cause:java.sql.SQLException:ORA-01013:用戶請求取消當前的操作

 

3、spring事務(wù)管理器配置

提供全局的事務(wù)級別的超時時間:

<bean id="oracleTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

  <property name="dataSource" ref="oracleDataSource" />

  <property name="defaultTimeout" value="2"/>

</bean>

 

總結(jié):

超時設(shè)置主要有以下幾個:

1、連接超時

2、讀數(shù)據(jù)超時

3、Statement超時

4、事務(wù)級別的超時=N* Statement超時 + GC 暫停time

 

之前總結(jié)過事務(wù)超時的一些問題,有興趣可以參考下:

http://jinnianshilongnian.iteye.com/blog/1986023

http://www.importnew.com/2466.html

 

另一個數(shù)據(jù)庫連接池需要注意的點:

<bean id="msqlDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">

如果沒有加destroy-method ,而且重啟次數(shù)太頻繁,造成重啟tomcat 舊的數(shù)據(jù)庫連接池的連接不釋放,這樣會有好多數(shù)據(jù)庫連接占著一段時間不釋放;所以最好加上destroy-method。

//////////////////////亂七八糟///////////////////////

當超過最大的連接數(shù)目的時候,會刪除連接。

if (config != null && config.getRemoveAbandoned() && (getNumIdle() < 2) && (getNumActive() > getMaxActive() - 3) ) {

  removeAbandoned();

}

這段代碼的作用是失效孤兒連接,即有人拿到連接但是沒有close的。 

 

1、網(wǎng)絡(luò)阻塞/不穩(wěn)定時的級聯(lián)效應(比如我現(xiàn)在寫的ssdb-client 在網(wǎng)絡(luò)出現(xiàn)故障(網(wǎng)絡(luò)不可用)時 我會設(shè)置一個時間,在這個時間內(nèi)的請求全部tiemout)

連接池內(nèi)部應該根據(jù)當前網(wǎng)絡(luò)的狀態(tài)(比如超時次數(shù)太多),對于一定時間內(nèi)的(如100ms)全部timeout,根本不進行await(maxWait)。

還有一個就是當前等待連接池的人數(shù),比如現(xiàn)在等待1000個,那么接下來的等待是沒有意義的,這樣還會造成滾雪球(ssdb-client采用了這種策略)。

2、等待超時應該盡可能小點(除非很必要),即使返回錯誤頁,也比等待強。

dbcp的比較容易出問題的地就是 設(shè)置的超時時間太長,造成大量的TIMED_WAIT,線程阻塞,而且是滾雪球,一旦出問題很難立即回復,而且這個可以通過[1]說的解決。 

 

大部分數(shù)據(jù)庫client都會有一個取消statement執(zhí)行的功能(即假設(shè)我們設(shè)置QueryTimeout=2秒,如果2秒內(nèi)沒返回信息,那么有個任務(wù)會主動發(fā)送一個取消的sql去取消當前statement的執(zhí)行)

1、mysql每個連接會創(chuàng)建一個Timer(每個Timer會創(chuàng)建一個Thread)

2、每創(chuàng)建一個Statement會提交一個TimerTask(每個Task在執(zhí)行時會創(chuàng)建一個Thread)

也就是說假設(shè)我們500個連接池,每個連接執(zhí)行1個statement,最壞的情況下會創(chuàng)建:

500*1+500*1=1000個線程。

假設(shè)一個應用中有三個mysql庫,那么最壞情況下有:

1000*3=3000個線程創(chuàng)建。

如果我們數(shù)據(jù)庫采用了分庫分表或者讀寫分離,可想而知。在壓力大的時候。

假設(shè)os對線程釋放不是特別快的話,cancel掉的線程可能并不是立即可用(我不確定,熟悉的同學可解釋下)。

 

而oracle采用不同的策略:

1、每個ClassLoader一個watchdog 線程(類似于mysql的timer);

2、每個Statement一個Task,而線程是在watchdog需要取消時去觸發(fā)的,即watchdog發(fā)現(xiàn)該Statement需要cancel時,調(diào)用其某個方法,該方法快速創(chuàng)建線程并運行;

也就是說假設(shè)我們500個連接池,每個連接執(zhí)行1個statement,最壞的情況下會創(chuàng)建:

1+500*1=501個線程。

假設(shè)一個應用中有三個mysql庫,那么最壞情況下有:

1 + 500*3=1501個線程創(chuàng)建。

解決方案:

1、最好的方案是改mysql實現(xiàn)。

2、修改底層系統(tǒng)支持的線程數(shù)。

//////////////////////亂七八糟///////////////////////

 

另外dbcp 1.x使用的是commons-pool 1.x,高并發(fā)下性能不是很好;考慮升級2.x或者如果新項目可以考慮使用druid或proxool,老項目還是慎重遷移(之前我遷移過是沒有問題的,不過還是慎重)。

 

===========================


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 印江| 潍坊市| 苍山县| 电白县| 临沧市| 通山县| 德州市| 沽源县| 泸定县| 田林县| 石首市| 武强县| 光泽县| 蒙山县| 合川市| 南充市| 平武县| 崇左市| 张家港市| 万载县| 赫章县| 清新县| 宜阳县| 繁峙县| 五峰| 宜君县| 崇阳县| 富顺县| 兴国县| 福贡县| 龙井市| 华坪县| 藁城市| 冷水江市| 土默特左旗| 新平| 鄂尔多斯市| 松溪县| 平遥县| 冕宁县| 汾西县|