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也會頗有可能初戀數據庫鏈接一直活躍被佔用
好了,這幾個地方注意下,基本上是能夠解決問題的