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的文檔以及在線說明發現,出現這種異常的原因是:

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

解決方案

解決的方法有3種:

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

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

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]后面添加上:

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 相關的參數說明

  • 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的時候,如果使用默認值,則數據庫連接因為某種原因斷掉后,再從連接池中取得連接又不進行驗證,這時取得的連接實際上就會是無效的數據庫連接。因此為了防止獲得的數據庫連接失效,在使用的時候最好保證:

  • 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/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM