myBatis鏈接MySQL報錯誤:No operations allowed after conn

myBatis鏈接MySQL報錯誤:No operations allowed after connection closed.Connection was i

www.MyException.Cn   發佈於:2013-07-16 22:38:05   瀏覽:253次html

0java

myBatis鏈接MySQL報異常:No operations allowed after connection closed.Connection was imysql

myBatis鏈接MySQL報異常:No operations allowed after connection closed.Connection was implicitly closed

 

異常信息

?linux

org.hibernate.exception.JDBCConnectionException: could not execute querysql

at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:74)數據庫

at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)apache

.......tomcat

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 **less

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 等於多少纔是合適的值呢? 因此並不推薦這個解決辦法。)

 

-------------------------相關-------------------------

 

1. 即便在建立Mysql時url中加入了autoReconnect=true參數,一但這個鏈接兩次訪問數據庫的時間超出了服務器端wait_timeout的時間限制,仍是會CommunicationsException: The last packet successfully received from the server was xxx milliseconds ago. 
2. 服務器端的參數能夠用 
  show global variables like 'wait_timeout'; 
  set global wait_timeout=10; 
  來進行設置,可是wait_timeout值不該該設的過高. 
3. 較好的策略是對處於idle狀態的connection定時發送一個sql,來刷新服務器上的時間戳.這可使用c3p0r的鏈接池.http://bzhang.iteye.com/blog/321832 
4. 對於tomcat的server.xml中使用的鏈接池,http://tomcat.apache.org/tomcat-6.0-doc/jndi-datasource-examples-howto.html,http://commons.apache.org/dbcp/configuration.html使用DBCP的鏈接池能夠採用 
<Resource name="jdbc/test" auth="Container"  
              type="javax.sql.DataSource" driverClassName="com.mysql.jdbc.Driver"  
              url="jdbc:mysql://localhost:3306/test?characterEncoding=utf-8"  
              username="root" password="test" maxActive="500" maxIdle="10"  
              maxWait="-1" timeBetweenEvictionRunsMillis="10000" minEvictableIdleTimeMillis="10000" /> 
  4.1 設置validationQuery,這樣每次borrow(默認爲開啓)時會經過這個sql校驗鏈接的有效性,可是增長了時間. 
  4.2 設置timeBetweenEvictionRunsMillis="10000" minEvictableIdleTimeMillis="10000" 依賴evictor thread線程來把超時的鏈接關閉. 
  4.3 設置testWhileIdle="true" timeBetweenEvictionRunsMillis="10000" validationQuery="select 1" 使得定時去用query檢測處於idle狀態的鏈接,也就刷新了服務器端的時間. 

5.每次提交的最大packet大小 
show global variables like 'max_allowed_packet'; 
set global max_allowed_packet=1024*1024; 

6. SQLyog 中鏈接參數的設置 
  6.1 在SQLyog中的設置 set autocommit=0,這樣當前鏈接的自動提交爲false,能夠控制事務了. 
  6.2 begin; 事務開始 
  6.3 select * from test where 1=1 and id =1 for update;這樣就把選到的記錄行鎖上了,再開一個SQLyog,也執行以上相同的操做,就會一直wait在那裏. 
  6.4 commit; 提交 
  6.5 rollback; 回滾 
  6.6 set autocommit=0;後應該加上 
      set transaction isolation level read committed; 
      這樣其它客戶端就能看到commit的數據, 
  疑問: 
      若是不設置set transaction isolation level read committed;若是兩個客戶端都select 相同的數據,一個客戶端修改而後提交,另外一個客戶端不提交當前事務的前提下,去執行select ,取不到另外一客戶端提交的數據,不知道SQLyog默認的事務級別是什麼樣的. 

7. SQLyog中查看mysql的狀態,show global variables like '%lock%'; 是個好方法.對於事務鎖(例如for update)報Lock wait timeout exceeded ,只能經過修改my.ini文件innodb_lock_wait_timeout = 100;才能生效. 

8. linux下修改用戶密碼 mysqladmin -u root password "new_pass"

 

後續有不少開發填坑的文章發佈,若是對你有幫助,請支持和加關注一下

http://e22a.com/h.05ApkG?cv=AAKHZXVo&sm=339944

https://shop119727980.taobao.com/?spm=0.0.0.0 

相關文章
相關標籤/搜索