com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after co

異常信息

org.hibernate.exception.JDBCConnectionException: could not execute query
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java: 74 )
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java: 43 )
.......
Caused by: com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException: No operations allowed after connection closed.Connection was implicitly closed due to underlying exception/error:
** BEGIN NESTED EXCEPTION **
com.mysql.jdbc.CommunicationsException
MESSAGE: Communications link failure due to underlying exception:
** BEGIN NESTED EXCEPTION **
java.net.SocketException
MESSAGE: Broken pipe
STACKTRACE:
java.net.SocketException: Broken pipe
at java.net.SocketOutputStream.socketWrite0(Native Method)
......
** END NESTED EXCEPTION **

緣由分析

查看了Mysql的文檔,以及Connector/J的文檔以及在線說明發現,出現這種異常的緣由是:html

  Mysql服務器默認的「wait_timeout」是8小時,也就是說一個connection空閒超過8個小時,Mysql將自動斷開該connection。這就是問題的所在,在C3P0 pools中的connections若是空閒超過8小時,Mysql將其斷開,而C3P0並不知道該connection已經失效,若是這時有Client請求connection,C3P0將該失效的Connection提供給Client,將會形成上面的異常。java

解決方案

解決的方法有3種:mysql

  1. 增長 wait_timeout 的時間。
  2. 減小 Connection pools 中 connection 的 lifetime。
  3. 測試 Connection pools 中 connection 的有效性。

固然最好的辦法是同時綜合使用上述3種方法,下面就 DBCP、C3P0 和 simple jdbc dataSource 分別作一說明,假設 wait_timeout 爲默認的8小時web

DBCP 增長如下配置信息:

複製代碼
validationQuery = "select 1"

testWhileIdle = "true"

//some positive integer
timeBetweenEvictionRunsMillis = 3600000

//set to something smaller than 'wait_timeout'
minEvictableIdleTimeMillis = 18000000

//if you don't mind a hit for every getConnection(), set to "true"
testOnBorrow = "true"
複製代碼

C3P0 增長如下配置信息:

複製代碼
//獲取connnection時測試是否有效
testConnectionOnCheckin = true

//自動測試的table名稱

automaticTestTable=C3P0TestTable

//set to something much less than wait_timeout, prevents connections from going stale
idleConnectionTestPeriod = 18000

//set to something slightly less than wait_timeout, preventing 'stale' connections from being handed out
maxIdleTime = 25000

//if you can take the performance 'hit', set to "true"
testConnectionOnCheckout = true
複製代碼

simple jdbc dataSource 增長如下配置信息:

複製代碼
Pool.PingQuery = select 1

Pool.PingEnabled = true

Pool.PingConnectionsOlderThan = 0

//對於空閒的鏈接一個小時檢查一次

Pool.PingConnectionsNotUsedFor = 3600000
複製代碼

其餘方案(不推薦)

  對於 MySQL5 以前的版本,如 Mysql4.x,只須要修改鏈接池配置中的 URL,添加一個參數:autoReconnect=true(如jdbc:mysql://hostaddress:3306/schemaname?autoReconnect=true),若是是 MySQL5 及之後的版本,則須要修改 my.cnf(或者my.ini) 文件,在 [mysqld]後面添加上:sql

wait_timeout = n
interactive-timeout = n

其中 n 爲服務器關閉交互式鏈接前等待活動的秒數。但是就部署而言每次修改 my.ini 比較麻煩,並且 n 等於多少纔是合適的值呢? 因此並不推薦這個解決辦法。)數據庫

 

原文地址:http://www.cnblogs.com/hemingwang0902/archive/2012/03/15/2397620.html服務器

 

附件:網絡

三大鏈接池的參數說明 

 

1. Apache-DBCP

? BasicDataSource 相關的參數說明app

  • dataSource: 要鏈接的 datasource (一般咱們不會定義在 server.xml)
  • defaultAutoCommit: 對於事務是否 autoCommit, 默認值爲 true
  • defaultReadOnly: 對於數據庫是否只能讀取, 默認值爲 false
  • driverClassName:鏈接數據庫所用的 JDBC Driver Class,
  • maxActive: 能夠從對象池中取出的對象最大個數,爲0則表示沒有限制,默認爲8
  • maxIdle: 最大等待鏈接中的數量,設 0 爲沒有限制 (對象池中對象最大個數)
  • minIdle:對象池中對象最小個數
  • maxWait: 最大等待秒數, 單位爲 ms, 超過期間會丟出錯誤信息
  • password: 登錄數據庫所用的密碼
  • url: 鏈接數據庫的 URL
  • username: 登錄數據庫所用的賬號
  • validationQuery: 驗證鏈接是否成功, SQL SELECT 指令至少要返回一行
  • removeAbandoned: 是否自我中斷, 默認是 false
  • removeAbandonedTimeout: 幾秒後會自我中斷, removeAbandoned 必須爲 true
  • logAbandoned: 是否記錄中斷事件, 默認爲 false
  • minEvictableIdleTimeMillis:大於0 ,進行鏈接空閒時間判斷,或爲0,對空閒的鏈接不進行驗證;默認30分鐘
  • timeBetweenEvictionRunsMillis:失效檢查線程運行時間間隔,若是小於等於0,不會啓動檢查線程,默認-1
  • testOnBorrow:取得對象時是否進行驗證,檢查對象是否有效,默認爲false
  • testOnReturn:返回對象時是否進行驗證,檢查對象是否有效,默認爲false
  • testWhileIdle:空閒時是否進行驗證,檢查對象是否有效,默認爲false

? 在使用DBCP的時候,若是使用默認值,則數據庫鏈接由於某種緣由斷掉後,再從鏈接池中取得鏈接又不進行驗證,這時取得的鏈接實際上就會是無效的數據庫鏈接。所以爲了防止得到的數據庫鏈接失效,在使用的時候最好保證:less

  • username: 登錄數據庫所用的賬號
  • validationQuerySELECT COUNT(*) FROM DUAL
  • testOnBorrowtestOnReturntestWhileIdle:最好都設爲true
  • minEvictableIdleTimeMillis:大於0 ,進行鏈接空閒時間判斷,或爲0,對空閒的鏈接不進行驗證
  • timeBetweenEvictionRunsMillis:失效檢查線程運行時間間隔,若是小於等於0,不會啓動檢查線程

? PS:在構造GenericObjectPool [BasicDataSource在其createDataSource () 方法中也會使用GenericObjectPool] 時,會生成一個內嵌類Evictor,實現自Runnable接口。若是timeBetweenEvictionRunsMillis大於0,每過timeBetweenEvictionRunsMillis毫秒Evictor會調用evict()方法,檢查對象的閒置時間是否大於 minEvictableIdleTimeMillis毫秒(_minEvictableIdleTimeMillis小於等於0時則忽略,默認爲30分鐘),是則銷燬此對象,不然就激活並校驗對象,而後調用ensureMinIdle方法檢查確保池中對象個數不小於_minIdle。在調用returnObject方法把對象放回對象池,首先檢查該對象是否有效,而後調用PoolableObjectFactory passivateObject方法使對象處於非活動狀態。再檢查對象池中對象個數是否小於maxIdle,是則能夠把此對象放回對象池,不然銷燬此對象

? 上述特性的可設置性已在代碼中驗證,具體性能是否能實現有待實際驗證

2. C3P0

? C3P0的官方example中使用的數據源爲ComboPooledDataSource,網上一篇文章詳細介紹了C3P0鏈接池配置中各項含義[這些配置項的含義在下載解壓c3p0的壓縮包以後目錄的doc\index.html中的Configuration部分也有詳細的介紹,這裏偷下懶:P],現摘錄以下:




3


30


1000


false


Test


">false


100


e">


null


nsactions">false


">60


3


60


15


100


on">


3


root


password





select id from test where id=1


300


">false


true


root


eProxies">false

con_test
    30000
    ">30
    10
    30
    25
    10
    0
    
    


    200
    
      300
    
   

? 上述特性的可設置性已在代碼中驗證,具體性能是否能實現有待實際驗證

? 從配置項的內容來看,C3P0DBCP都有比較詳細的有關鏈接檢測保證的配置,咱們能夠看到C3P0能夠控制數據源內加載的PreparedStatements數量,而且能夠設置幫助線程的數量來提高JDBC操做的速度這些是DBCP未提供的;另外從網絡上的評價來看,DBCP出現Bug的頻率要大於C3P0,不過這一點有待於咱們本身實際的檢測。

3. Proxool

? Proxool的使用和dbcp以及c3p0稍有不一樣,咱們須要而且只須要在使用基本的java.sql.DriverManager以前加載org.logicalcobwebs.proxool.ProxoolDriver驅動類,而且按照proxool定義的url格式 ["proxool." + alias + ":" + driverClass + ":" + driverUrl ,其中alias是爲鏈接池自定義的別名] 來得到connection;具體的能夠參看proxool doc下的UserGuide,或本文所附的示例代碼。下面對鏈接池的特性配置做詳細說明 [這個是本身翻譯的,不必定準確,有問題時請參看doc下的Properties ~]

n fatal-sql-exception

以逗號隔開的異常列表,當設置了此項以後,每當出現SQLException時都將與列表中異常項做比較,若是匹配則認爲出現fatal異常,這將致使connection被丟棄,而且不論出現任何狀況該異常將被重拋一次以通知用戶發生的狀況。默認值爲null

n fatal-sql-exception-wrapper-class

若是配置了fatal-sql-exception,則默認的操做是丟 棄引發SQLException的緣由而只是拋出原始異常。使用fatal-sql-exception-wrapper-class這個特性能夠將 SQLException包裝到繼承SQLException或RunTimeException的任何異常類裏。Proxool提供了兩個類供使用 FatalSQLException和FatalRunTimeException;使用這兩個類的話就將該選項設置爲 'org.logicalcobwebs.proxool.FatalSQLException'或者 'org.logicalcobwebs.proxool.FatalRuntimeException'。默認值爲null

n house-keeping-sleep-time

proxool自動偵察各個鏈接狀態的時間間隔(毫秒),偵察到空閒的鏈接就立刻回收,超時的銷燬,默認值爲30

n house-keeping-test-sql

若是偵察線程發現閒置鏈接,則會使用這個SQL語句來對這些鏈接進行檢查;這項設置的語句應該可以被很快的執行,例如查詢當前時間 [info.setProperty("proxool.house-keeping-test-sql", "select CURRENT_DATE");] 。若是不設置則該選項被忽略

n injectable-connection-interfaceinjectable-statement-interfaceinjectable-prepared-statement-interfaceinjectable-callable-statement-interface

n jmx

若是此項設爲true,則鏈接池將被以名稱"Proxool:type=Pool, name="註冊爲JMS Server的MBean。默認值爲false

n jmx-agent-id

當且僅當jmx選項設爲true時使用,爲以逗號分隔的鏈接持註冊到的JMS代理名稱列表;若是不設置則全部註冊的JMX Server都將被使用

n maximum-active-time

線程最大存活時間,超過此時間的線程將被守護線程kill掉,默認值爲5分鐘

n maximum-connection-count

到數據庫的最大鏈接數,超過了這個鏈接,再有請求時,就排在隊列中等候,最大的等待請求數由simultaneous-build-throttle決定;默認值爲15

n maximum-connection-lifetime

鏈接最大存活時間,毫秒爲單位,默認值爲4小時

n minimum-connection-count

不論是否被使用都保持開放的最小鏈接數,默認值爲5

n overload-without-refusal-lifetime

用來判斷鏈接池狀態,若是在此選項設置時間內(毫秒爲單位)拒絕了鏈接,則認爲過負載。默認值爲60

n prototype-count

最少保持的空閒鏈接數,注意與minimum-connection-count區分。默認值爲0

n simultaneous-build-throttle

最大的等待請求數,默認值爲10

n test-before-use

若是設爲true則connection在使用前將以house-keeping-test-sql設置的語句測試,若是測試不經過則該connection被丟棄並會從新分配一個connection。默認爲false

n test-after-use

若是設爲true則connection在關閉(放回鏈接池)前將以house-keeping-test-sql設置的語句測試,若是測試不經過connection將被丟棄。默認值爲false

? 與其它鏈接池特性的設置方法不一樣,Proxool不提供相應的set方法,全部特性都要以諸如info.setProperty("proxool.jmx", "false");方式設定

? 上述特性的可設置性已在代碼中驗證,具體性能是否能實現有待實際驗證

 

原文地址:http://zhangsha1251.blog.163.com/blog/static/62624053201182111921783/

相關文章
相關標籤/搜索