sql 鏈接數不釋放 ,Druid異常:wait millis 40000, active 600, maxActive 600

Hibernate + Spring + Druid 數據庫mysqljava

因爲配置以下mysql

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
		<property name="url" value="${datasource.url}" />
		<property name="username" value="${datasource.username}" />
		<property name="password" value="${datasource.password}" />
 		<!-- 驅動類 -->
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />

		<!-- 默認自動提交狀態。若是不設置,則setAutoCommit 方法將不被調用 -->
		<property name="defaultAutoCommit" value="true" />
		<!-- 屬性類型是字符串,經過別名的方式配置擴展插件,經常使用的插件有:監控統計用的filter:stat 日誌用的filter:log4j 防護sql注入的filter:wall -->
		<!-- <property name="filters" value="stat" /> -->
		<property name="filters" value="config,stat,log4j" />
		<!-- 能夠在這個池中同時被分配的有效鏈接數的最大值 -->
		<property name="maxActive" value="600" />
		<!-- 初始化時創建物理鏈接的個數。初始化發生在顯示調用init方法,或者第一次getConnection時 -->
		<property name="initialSize" value="2" />
		<!-- 獲取鏈接時最大等待時間,單位毫秒。配置了maxWait以後,缺省啓用公平鎖,併發效率會有所降低,若是須要能夠經過配置useUnfairLock屬性爲true使用非公平鎖。-->
		<property name="maxWait" value="40000" />
		<!-- 最小鏈接池數量 -->
		<property name="minIdle" value="0" />
		<!-- 有兩個含義:1) Destroy線程會檢測鏈接的間隔時間  2) testWhileIdle的判斷依據,詳細看testWhileIdle屬性的說明 -->
		<property name="timeBetweenEvictionRunsMillis" value="60000" />
		<!-- Destory線程中若是檢測到當前鏈接的最後活躍時間和當前時間的差值大於 minEvictableIdleTimeMillis,則關閉當前鏈接 -->
		<property name="minEvictableIdleTimeMillis" value="8000" />
		<!-- 用來檢測鏈接是否有效的sql,要求是一個查詢語句。若是validationQuery爲null,testOnBorrow、testOnReturn、testWhileIdle都不會其做用。
			 在mysql中一般爲select 'x',在oracle中一般爲select 1 from dual -->
		<property name="validationQuery" value="select 1 from dual" />
		<!-- 建議配置爲true,不影響性能,而且保證安全性。申請鏈接的時候檢測,若是空閒時間大於timeBetweenEvictionRunsMillis,執行validationQuery檢測鏈接是否有效。 -->
		<property name="testWhileIdle" value="false" />
		<!-- 申請鏈接時執行validationQuery檢測鏈接是否有效,作了這個配置會下降性能。-->
		<property name="testOnBorrow" value="false" />
		<!-- 歸還鏈接時執行validationQuery檢測鏈接是否有效,作了這個配置會下降性能 -->
		<property name="testOnReturn" value="false" />
		<!-- 要啓用PSCache,必須配置大於0,當大於0時,poolPreparedStatements自動觸發修改成true。在Druid中,不會存在Oracle下PSCache佔用內存過多的問題,能夠把這個數值配置大一些,好比說100 -->
		<property name="maxOpenPreparedStatements" value="200" />
		<!-- 對於創建時間超過removeAbandonedTimeout的鏈接強制關閉 -->
		<property name="removeAbandoned" value="true" /> <!-- 打開removeAbandoned功能 -->
		<!-- 180秒,也就是3分鐘 -->
		<property name="removeAbandonedTimeout" value="1800" />
		<!-- 關閉abanded鏈接時輸出錯誤日誌 -->
		<property name="logAbandoned" value="true" />
	</bean>

從配置能夠看到,個人鏈接數max = 600, 可是程序跑到不到一會就報鏈接數不夠, 獲取不了鏈接數就一直卡在那裏,重啓tomcat服務器,過一會又是這樣spring

從數據庫  SHOW PROCESSLIST 發現好多鏈接數在 sleep , sleep 說明鏈接數沒有被釋放一直在被佔用sql

 

分析思路數據庫

1 分析代碼中可能有沒有 未關閉的數據庫鏈接tomcat

2 查看配置文件時候正確安全

 

代碼中服務器

若是代碼中出現 Session session =  getSession(); 最後最好加上 session.close(); 這樣就手動釋放了這個鏈接,也能夠換一種獲取鏈接的方式session

public class UniversalDao extends HibernateDaoSupport
{
  public void delete(Class clazz, Serializable id)
  {
    getHibernateTemplate().delete(get(clazz, id));
  }

  public List findByCriteria(DetachedCriteria criteria) {
    return getHibernateTemplate().findByCriteria(criteria);
  }
}

這樣 getHibernateTemplate() 獲取數據鏈接併發

 

配置文件中

  <!-- 對於創建時間超過removeAbandonedTimeout的鏈接強制關閉 -->
  <property name="removeAbandoned" value="true" /> <!-- 打開removeAbandoned功能 -->
  <!-- 180秒,也就是3分鐘 -->
  <property name="removeAbandonedTimeout" value="180" /> <!-- 世界設置小 3分鐘sleep 直接強制關閉 -->
  <!-- 關閉abanded鏈接時輸出錯誤日誌 -->
  <property name="logAbandoned" value="true" />

  關聯hibernate 配置中

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect"> ${hibernate.dialect} </prop>
				<prop key="hibernate.show_sql"> ${hibernate.show_sql} </prop>
				<prop key="hibernate.jdbc.fetch_size"> ${hibernate.jdbc.fetch_size} </prop>
				<prop key="hibernate.jdbc.batch_size"> ${hibernate.jdbc.batch_size} </prop>
				<prop key="hibernate.format_sql"> ${hibernate.format_sql} </prop>
				<prop key="hibernate.c3p0.max_statements"> ${hibernate.c3p0.max_statements} </prop>
        		<prop key="hibernate.hbm2ddl.auto">none</prop>
        		<prop key="hibernate.connection.release_mode">after_transaction</prop>
			</props>
		</property>

 屬性  key="hibernate.connection.release_mode" 這一列要填 after_transaction, 若是是auto也會頗有可能初戀數據庫鏈接一直活躍被佔用

好了,這幾個地方注意下,基本上是能夠解決問題的

相關文章
相關標籤/搜索