ivaneeo's blog

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

            BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
            669 Posts :: 0 Stories :: 64 Comments :: 0 Trackbacks

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

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

          it/科技

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

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

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

                4. 最后,還有一個就是DBCP的maxWait參數,該參數值不宜配置太大,因為在池消耗滿時,該會掛起線程等待一段時間看看是否能獲得連接,一般到池耗盡的可能很少,若真要耗盡了一般也是并發太大,若此時再掛線程的話,也就是同時掛起了Server的線程,若到Server線程也掛滿了,不光是訪問DB的線程無法訪問,就連訪問普通頁面也無法訪問了。結果是更糕。

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

           

          2.ibatis使用dbcp連接數據庫

          一、建立數據表(我用的是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,所以加了一個空格)
          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

          #連接設置
          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

          #最大連接數量
          maxActive=50

          #是否在自動回收超時連接的時候打印連接的超時錯誤
          logAbandoned=true

          #是否自動回收超時連接
          removeAbandoned=true

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

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


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

          注:如果是用main類測試則應在工程目錄的classes下,如果是站點測試則在web-inf的classes目錄下

          五、寫ibatis與DBCP的關系文件

          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"/> (注:這里對應表映射)
          </sqlMapConfig>

          六、寫數據表映射文件

          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,所以加了一個空格)
            </delete>

          </sqlMap>

           

          posted on 2011-04-22 13:45 ivaneeo 閱讀(1062) 評論(0)  編輯  收藏 所屬分類: java魔力
          主站蜘蛛池模板: 大石桥市| 资中县| 远安县| 扶余县| 台中市| 长丰县| 军事| 宿松县| 长泰县| 峨眉山市| 皋兰县| 瓮安县| 宜章县| 亳州市| 葫芦岛市| 黔东| 罗定市| 阳新县| 山西省| 迁西县| 宜宾市| 肥城市| 卢龙县| 大姚县| 伊春市| 五指山市| 宁化县| 哈密市| 宜黄县| 万宁市| 清水县| 宜城市| 楚雄市| 尼木县| 车险| 扎鲁特旗| 仙游县| 商都县| 三都| 山丹县| 同仁县|