ivaneeo's blog

          自由的力量,自由的生活。

            BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
            669 Posts :: 0 Stories :: 64 Comments :: 0 Trackbacks

          ibatis dbcp連接數(shù)據(jù)庫問題(上)

           (2007-12-20 22:43:33)
          標(biāo)簽: 

          it/科技

          分類: javaEE
          我是懶人,就不自己寫了,就直接引用我找到的兩篇博文:
          最近網(wǎng)站會出現(xiàn)一個(gè)現(xiàn)象是,在并發(fā)量大的時(shí)候,Tomcat或JBoss的服務(wù)線程會線程掛起,同時(shí)服務(wù)器容易出現(xiàn)數(shù)據(jù)連接的 java.net.SocketException: Broken pipe  的錯(cuò)誤。剛才開始咋一看感覺像是DB端處理不來或是DB端的連接時(shí)間到了wait_timeout 的時(shí)間強(qiáng)行斷開。出于這兩個(gè)目的,網(wǎng)收集了一些資料后,有的說法是在DB的 wait_timeout 時(shí)間后斷開的一些連接在連接池中處于空閑狀態(tài),當(dāng)應(yīng)用層獲取該連接后進(jìn)行的DB操作就會發(fā)生上面這個(gè)錯(cuò)誤。
               但在我查看了DBCP連接池代碼和做了些測試后,發(fā)生這種說法并非正確。
               1. 首先,出現(xiàn) Broken pipe 的錯(cuò)誤不是因連接超時(shí)所致,這個(gè)錯(cuò)誤只有在Linux下多發(fā),就是在高并發(fā)的情況下,網(wǎng)絡(luò)資源不足的情況出現(xiàn)的, 會發(fā)送SIGPIPE信號,LINUX下默認(rèn)程序退出的,具體解決辦法目前還未找到合適的,有的說法是在Linux的環(huán)境變量中設(shè)置: _JAVA_SR_SIGNUM = 12 基本就可以解決,但經(jīng)測試結(jié)果看并未解決。對于該問題持續(xù)關(guān)注中。
               2. 之后,Broken pipe 問題未徹底解決,那么對于DBCP連接池只好對一些作廢的連接要進(jìn)行強(qiáng)制回收,若這里不做強(qiáng)制回收的話,最終也就會導(dǎo)致 pool exhausted 了,所以這一步一定要加上保護(hù)。配置如下:
          1. #### 是否在自動(dòng)回收超時(shí)連接的時(shí)候打印連接的超時(shí)錯(cuò)誤   
          2. dbcp.logAbandoned=true  
          3. #### 是否自動(dòng)回收超時(shí)連接   
          4. dbcp.removeAbandoned=true  
          5. #### 超時(shí)時(shí)間(以秒數(shù)為單位)   
          6. dbcp.removeAbandonedTimeout=150  

               3. 對于DB的 wait_timeout 空閑連接時(shí)間設(shè)置,在超過該時(shí)間值的連接,DB端會強(qiáng)行關(guān)閉,經(jīng)測試結(jié)果,即使DB強(qiáng)行關(guān)閉了空閑連接,對于DBCP而言在獲取該連接時(shí)無法激活該連接,會自動(dòng)廢棄該連接,重新從池中獲取空閑連接或是重新創(chuàng)建連接,從源代碼上看,這個(gè)自動(dòng)完成的激活邏輯并不需要配置任何參數(shù),是DBCP的默認(rèn)操作。故對于網(wǎng)上的不少說連接池時(shí)間配置與DB不協(xié)調(diào)會導(dǎo)致 Broken pipe 的說法是錯(cuò)誤,至少對于DBCP是不會出現(xiàn)該問題,也許C3P0是這樣。
                不過對于連接池的優(yōu)化而言,本來就在池里空閑的連接被DB給強(qiáng)行關(guān)閉也不件好事,這里可以組合以下幾個(gè)配置解決該問題:

          java 代碼
          1. false 空閑時(shí)是否驗(yàn)證, 若不通過斷掉連接, 前提是空閑對象回收器開啟狀態(tài)   
          2. dbcp.testWhileIdle true  
          3. -1 以毫秒表示空閑對象回收器由運(yùn)行間隔。值為負(fù)數(shù)時(shí)表示不運(yùn)行空閑對象回收器   
          4. 若需要回收, 該值最好小于 minEvictableIdleTimeMillis 值   
          5. dbcp.timeBetweenEvictionRunsMillis 300000 
          6. 1000*60*30 被空閑對象回收器回收前在池中保持空閑狀態(tài)的最小時(shí)間, 毫秒表示   
          7. 若需要回收, 該值最好小于DB中的 wait_timeout   
          8. dbcp.minEvictableIdleTimeMillis 320000  

                4. 最后,還有一個(gè)就是DBCP的maxWait參數(shù),該參數(shù)值不宜配置太大,因?yàn)樵诔叵臐M時(shí),該會掛起線程等待一段時(shí)間看看是否能獲得連接,一般到池耗盡的可能很少,若真要耗盡了一般也是并發(fā)太大,若此時(shí)再掛線程的話,也就是同時(shí)掛起了Server的線程,若到Server線程也掛滿了,不光是訪問DB的線程無法訪問,就連訪問普通頁面也無法訪問了。結(jié)果是更糕。

                  這樣,通過以上幾個(gè)配置,DBCP連接池的連接泄漏應(yīng)該不會發(fā)生了(當(dāng)然除了程序上的連接泄漏),不過對于并發(fā)大時(shí)Linux上的BrokenPipe 問題最好能徹底解決。但是對于并發(fā)量大時(shí),Tomcat或JBoss的服務(wù)線程會掛起的原因還是未最終定位到原因,目前解決了DBCP的影響后,估計(jì)問題可能會是出現(xiàn)在 mod_jk 與 Tomcat 的連接上了,最終原因也有可能是 broken pipe 所致。關(guān)注與解決中……

           

          2.ibatis使用dbcp連接數(shù)據(jù)庫

          一、建立數(shù)據(jù)表(我用的是oracle 9.2.0.1)

          prompt PL/SQL Developer import file
          prompt Created on 2007年5月24日 by Administrator
          set feedback off
          set define off
          prompt Dropping T_ACCOUNT...
          dro p table T_ACCOUNT cascade constraints; (注意:這里由于ISP限制上傳drop,所以加了一個(gè)空格)
          prompt Creating T_ACCOUNT...
          create table T_ACCOUNT
          (
            ID           NUMBER not null,
            FIRSTNAME    VARCHAR2(2),
            LASTNAME     VARCHAR2(4),
            EMAILADDRESS VARCHAR2(60)
          )
          ;
          alter table T_ACCOUNT
            add constraint PK_T_ACCOUNT primary key (ID);

          prompt Disabling triggers for T_ACCOUNT...
          alter table T_ACCOUNT disable all triggers;
          prompt Loading T_ACCOUNT...
          insert into T_ACCOUNT (ID, FIRSTNAME, LASTNAME, EMAILADDRESS)
          values (1, '王', '三旗', 'E_wsq@msn.com');
          insert into T_ACCOUNT (ID, FIRSTNAME, LASTNAME, EMAILADDRESS)
          values (2, '冷', '宮主', 'E_wsq@msn.com');
          commit;
          prompt 2 records loaded
          prompt Enabling triggers for T_ACCOUNT...
          alter table T_ACCOUNT enable all triggers;
          set feedback on
          set define on
          prompt Done.


          二、在工程中加入

          commons-dbcp-1.2.2.jar

          commons-pool-1.3.jar

          ibatis-common-2.jar

          ibatis-dao-2.jar

          ibatis-sqlmap-2.jar

          三、編寫如下屬性文件

          jdbc.properties

          #連接設(shè)置
          driverClassName=oracle.jdbc.driver.OracleDriver
          url=jdbc:oracle:thin:@90.0.12.112:1521:ORCL
          username=gzfee
          password=1

          #<!-- 初始化連接 -->
          initialSize=10

          #<!-- 最大空閑連接 -->
          maxIdle=20

          #<!-- 最小空閑連接 -->
          minIdle=5

          #最大連接數(shù)量
          maxActive=50

          #是否在自動(dòng)回收超時(shí)連接的時(shí)候打印連接的超時(shí)錯(cuò)誤
          logAbandoned=true

          #是否自動(dòng)回收超時(shí)連接
          removeAbandoned=true

          #超時(shí)時(shí)間(以秒數(shù)為單位)
          removeAbandonedTimeout=180

          #<!-- 超時(shí)等待時(shí)間以毫秒為單位 6000毫秒/1000等于60秒 -->
          maxWait=1000


          四、將上面建立的屬性文件放入classes下

          注:如果是用main類測試則應(yīng)在工程目錄的classes下,如果是站點(diǎn)測試則在web-inf的classes目錄下

          五、寫ibatis與DBCP的關(guān)系文件

          DBCPSqlMapConfig.xml

          <?xml version="1.0" encoding="UTF-8" ?>

          <!DOCTYPE sqlMapConfig     
              PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"     
              "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">

          <sqlMapConfig>
              <properties resource ="jdbc.properties"/>
              <transactionManager  type ="JDBC">
                <dataSource  type ="DBCP">
                     <property  name ="JDBC.Driver"  value ="${driverClassName}"/>
                     <property  name ="JDBC.ConnectionURL"  value ="${url}" />
                     <property  name ="JDBC.Username"  value ="${username}" />
                     <property  name ="JDBC.Password"  value ="${password}" />
                     <property  name ="Pool.MaximumWait"  value ="30000" />
                     <property  name ="Pool.ValidationQuery"  value ="select sysdate from dual" />
                     <property  name ="Pool.LogAbandoned"  value ="true" />
                     <property  name ="Pool.RemoveAbandonedTimeout"  value ="1800000" />
                     <property  name ="Pool.RemoveAbandoned"  value ="true" />
                </dataSource>
              </transactionManager>
              <sqlMap resource="com/mydomain/data/Account.xml"/> (注:這里對應(yīng)表映射)
          </sqlMapConfig>

          六、寫數(shù)據(jù)表映射文件

          Account.xml

          <?xml version="1.0" encoding="UTF-8" ?>

          <!DOCTYPE sqlMap     
              PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN"     
              "http://ibatis.apache.org/dtd/sql-map-2.dtd">

          <sqlMap namespace="Account">

            <!-- Use type aliases to avoid typing the full classname every time. -->
            <typeAlias alias="Account" type="com.mydomain.domain.Account"/>

            <!-- Result maps describe the mapping between the columns returned
                 from a query, and the class properties.  A result map isn't
                 necessary if the columns (or aliases) match to the properties
                 exactly. -->
            <resultMap id="AccountResult" class="Account">
              <result property="id" column="id"/>
              <result property="firstName" column="firstName"/>
              <result property="lastName" column="lastName"/>
              <result property="emailAddress" column="emailAddress"/>
            </resultMap>

            <!-- Select with no parameters using the result map for Account class. -->
            <select id="selectAllAccounts" resultMap="AccountResult">
              select * from T_ACCOUNT
            </select>

            <!-- A simpler select example without the result map.  Note the
                 aliases to match the properties of the target result class. -->
            <select id="selectAccountById" parameterClass="int" resultClass="Account">
              select
                id as id,
                firstName as firstName,
                lastName as lastName,
                emailAddress as emailAddress
              from T_ACCOUNT
              where id = #id#
            </select>
            
            <!-- Insert example, using the Account parameter class -->
            <insert id="insertAccount" parameterClass="Account">
              insert into T_ACCOUNT (
                id,
                firstName,
                lastName,
                emailAddress
              values (
                #id#, #firstName#, #lastName#, #emailAddress#
              )
            </insert>

            <!-- Update example, using the Account parameter class -->
            <update id="updateAccount" parameterClass="Account">
              update T_ACCOUNT set
                firstName = #firstName#,
                lastName = #lastName#,
                emailAddress = #emailAddress#
              where
                id = #id#
            </update>

            <!-- Delete example, using an integer as the parameter class -->
            <delete id="deleteAccountById" parameterClass="int">
              delet e from T_ACCOUNT where id = #id# (注意:這里由于ISP限制上傳delete,所以加了一個(gè)空格)
            </delete>

          </sqlMap>

           

          posted on 2011-04-22 13:45 ivaneeo 閱讀(1058) 評論(0)  編輯  收藏 所屬分類: java魔力
          主站蜘蛛池模板: 武汉市| 霍邱县| 淮北市| 泊头市| 钦州市| 营山县| 岳池县| 泰和县| 富阳市| 东乌珠穆沁旗| 普洱| 麻江县| 长沙县| 新营市| 佛坪县| 定襄县| 资中县| 镇江市| 盈江县| 新源县| 勃利县| 毕节市| 葵青区| 广德县| 定安县| 嵩明县| 贵港市| 蒲江县| 那曲县| 镇坪县| 尼木县| 大足县| 湘潭市| 青川县| 安陆市| 肃宁县| 武功县| 华安县| 深泽县| 湖南省| 赣榆县|