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 

相关文章
相关标签/搜索