1. 程式人生 > >MySql 8小時解決方案:proxool連線池

MySql 8小時解決方案:proxool連線池

最近做的專案用的mysql資料庫,前天掛在伺服器上,昨天早晨上班一來,同事就說API資料介面訪問不了了,我馬上mstsc登陸伺服器看,報錯了。馬上重啟tomcat,結果還能正常執行,當時沒管,今天過來又出現相同的問題,錯誤程式碼網上一查,原來是MySql8小時的問題。

MySql8小時問題:

MySQL 的預設設定下,當一個連線的空閒時間超過8小時後,MySQL 就會斷開該連線,而 c3p0 連線池則以為該被斷開的連線依然有效。在這種情況下,如果客戶端程式碼向 c3p0 連線池請求連線的話,連線池就會把已經失效的連線返回給客戶端,客戶端在使用該失效連線的時候即丟擲異常。

解決方案一:

增加 MySQL 的 wait_timeout 屬性的值。

這兩個引數的預設值是8小時(60*60*8=28800)。我測試過將這兩個引數改為0,結果出人意料,系統自動將這個值設定為。換句話說,不能將該值設定為永久。 

將這2個引數設定為24小時(60*60*24=604800)即可。  set interactive_timeout=604800;  set wait_timeout=604800; 

總結:可以短時間內解決該問題,但是時間還有有限制,不是完美的解決方案。

解決方案二:

Proxool是一種Java資料庫連線池技術。是sourceforge下的一個開源專案,這個專案提供一個健壯、易用的連線池,最為關鍵的是這個連線池提供監控的功能,方便易用,便於發現連線洩漏的情況。

步驟1:將proxool支援的jar拷貝到專案的WEB-INF/lib目錄中


步驟2:src下建立proxool.xml(跟hibernate相同路徑)

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

<something-else-entirely>
	<proxool>
		<alias>mysql</alias> 
		<driver-url>jdbc:mysql://localhost:3306/資料庫名</driver-url>
		<driver-class>com.mysql.jdbc.Driver</driver-class>
		<driver-properties>
			<property name="user" value="root" />
			<property name="password" value="admin" />
		</driver-properties> 
		<!--最大連線數(預設5個),超過了這個連線數,再有請求時,就排在佇列中等候,最大的等待請求數由maximum-new-connections決定 --> 
		<maximum-connection-count>100</maximum-connection-count> 
		<!--最小連線數(預設2個)-->  
		<minimum-connection-count>10</minimum-connection-count> 
		<!--proxool自動偵察各個連線狀態的時間間隔(毫秒),偵察到空閒的連線就馬上回收,超時的銷燬 預設30秒-->  
		<house-keeping-sleep-time>90000</house-keeping-sleep-time>
		<!--沒有空閒連線可以分配而在佇列中等候的最大請求數,超過這個請求數的使用者連線就不會被接受--> 
		<maximum-new-connections>10</maximum-new-connections> 
		<!--最少保持的空閒連線數(預設2個)-->  
		<prototype-count>5</prototype-count> 
		<!--在使用之前測試--> 
		<test-before-use>true</test-before-use>
		<!--用於保持連線的測試語句 --> 
		<house-keeping-test-sql>select now()</house-keeping-test-sql>
	</proxool>
</something-else-entirely> 

步驟3:Hibernate配置檔案新增proxool連線池

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<!-- Generated by MyEclipse Hibernate Tools.                   -->
<hibernate-configuration>

	<session-factory>
	 	<property name="hibernate.connection.provider_class">org.hibernate.connection.ProxoolConnectionProvider</property>
		<!-- proxool.xml中對應<alias>mysql</alias>的名稱  -->
		<property name="hibernate.proxool.pool_alias">
			mysql
		</property>
		<!-- proxool.xml的路徑,因為在同一目錄下,所以直接填寫proxool.xml(相對路徑)  -->
		<property name="hibernate.proxool.xml">
			proxool.xml
		</property>
		<property name="dialect">
			org.hibernate.dialect.MySQLDialect
		</property>

		<property name="show_sql">true</property>
		<mapping resource="com/donen/pojo/User.hbm.xml" />

	</session-factory>

</hibernate-configuration>

這樣就可以在hiernate中使用proxool連線池了。不需要更改mysql配置解決8小時問題。

附:proxool連線池使用情況檢視

在web.xml中新增如下內容
<servlet>
	<servlet-name>dbpoolAdmin</servlet-name>
	<servlet-class>org.logicalcobwebs.proxool.admin.servlet.AdminServlet</servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name>dbpoolAdmin</servlet-name>
	<url-pattern>/dbpool</url-pattern>
</servlet-mapping>
之後訪問http://localhost:埠號/專案名稱/dbpool 即可檢視連線池當前資訊(訪問此頁前至少要訪問一個有對資料庫進行操作的頁面

附:proxool屬性說明

屬性列表說明:

fatal-sql-exception: 它是一個逗號分割的資訊片段.當一個SQL異常發生時,他的異常資訊將與這個資訊片段進行比較.如果在片段中存在,那麼這個異常將被認為是個致命錯誤(Fatal SQL Exception ).這種情況下,資料庫連線將要被放棄.無論發生什麼,這個異常將會被重擲以提供給消費者.使用者最好自己配置一個不同的異常來丟擲.

fatal-sql-exception-wrapper-class:正如上面所說,你最好配置一個不同的異常來重擲.利用這個屬性,使用者可以包裝SQLException,使他變成另外一個異常.這個異常或者繼承SQLException或者繼承字RuntimeException.proxool自帶了2個實現:'org.logicalcobwebs.proxool.FatalSQLException' 和'org.logicalcobwebs.proxool.FatalRuntimeException' .後者更合適.

house-keeping-sleep-time: house keeper 保留執行緒處於睡眠狀態的最長時間,house keeper 的職責就是檢查各個連線的狀態,並判斷是否需要銷燬或者建立.

house-keeping-test-sql:  如果發現了空閒的資料庫連線.house keeper 將會用這個語句來測試.這個語句最好非常快的被執行.如果沒有定義,測試過程將會被忽略。

injectable-connection-interface: 允許proxool實現被代理的connection物件的方法.

injectable-statement-interface: 允許proxool實現被代理的Statement 物件方法.

injectable-prepared-statement-interface: 允許proxool實現被代理的PreparedStatement 物件方法.

injectable-callable-statement-interface: 允許proxool實現被代理的CallableStatement 物件方法.

jmx: 略

jmx-agent-id: 略

jndi-name: 資料來源的名稱

maximum-active-time: 如果housekeeper 檢測到某個執行緒的活動時間大於這個數值.它將會殺掉這個執行緒.所以確認一下你的伺服器的頻寬.然後定一個合適的值.預設是5分鐘.

maximum-connection-count: 最大的資料庫連線數.

maximum-connection-lifetime: 一個執行緒的最大壽命.

minimum-connection-count: 最小的資料庫連線數

overload-without-refusal-lifetime: 略

prototype-count: 連線池中可用的連線數量.如果當前的連線池中的連線少於這個數值.新的連線將被建立(假設沒有超過最大可用數).例如.我們有3個活動連線2個可用連線,而我們的prototype-count是4,那麼資料庫連線池將試圖建立另外2個連線.這和 minimum-connection-count不同. minimum-connection-count把活動的連線也計算在內.prototype-count 是spare connections 的數量.

recently-started-threshold:  略

simultaneous-build-throttle:  略

statistics 連線池使用狀況統計。 引數“10s,1m,1d”

statistics-log-level:  日誌統計跟蹤型別。 引數“ERROR”或 “INFO”

test-before-use: 略

test-after-use: 略

trace: 如果為true,那麼每個被執行的SQL語句將會在執行期被log記錄(DEBUG LEVEL).你也可以註冊一個ConnectionListener (參看ProxoolFacade)得到這些資訊.

verbose: 詳細資訊設定。 引數 bool 值