请教下关于jdbc的rollback产生的异常的问题

shadowlin 2008-10-10 01:35:47
昨天跑程序发现了个以前一直没碰到过的异常.


2008-10-10 04:40:28,708 <WARN> [main] (CommonDAO.java:63) : Can not rollback
2008-10-10 04:40:28,709 <WARN> [main] (CommonDAO.java:64) : com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException: Connection.close() has already been called. Invalid operation in this state.
2008-10-10 04:40:28,710 <WARN> [main] (CommonDAO.java:63) : Can not rollback
2008-10-10 04:40:28,757 <WARN> [main] (CommonDAO.java:64) : com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException: Connection.close() has already been called. Invalid operation in this state.
2008-10-10 04:40:28,758 <WARN> [main] (MultiThreadCrawler.java:231) : com.mysql.jdbc.CommunicationsException: Communications link failure due to underlying exception:

** BEGIN NESTED EXCEPTION **

java.io.EOFException

STACKTRACE:

java.io.EOFException
at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:1913)
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2304)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2803)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1573)
at com.mysql.jdbc.ServerPreparedStatement.serverExecute(ServerPreparedStatement.java:1169)
at com.mysql.jdbc.ServerPreparedStatement.executeInternal(ServerPreparedStatement.java:693)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1404)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1318)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1303)
at com.mnv.dao.MDBMovieDAO.saveOrUpdateMovie(MDBMovieDAO.java:68)
at com.mnv.core.crawlers.MultiThreadCrawler.startCrawler(MultiThreadCrawler.java:203)
at com.mnv.core.crawlers.mainentries.CrawlerMainEntry.crawlerMain(CrawlerMainEntry.java:53)
at com.mnv.core.crawlers.mainentries.Main.main(Main.java:26)


** END NESTED EXCEPTION **



Last packet sent to the server was 815930 ms ago.
2008-10-10 04:40:28,758 <WARN> [main] (CommonDAO.java:23) : Can not start transaciton
2008-10-10 04:40:28,758 <WARN> [main] (CommonDAO.java:24) : com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException: Connection.close() has already been called. Invalid operation in this state.
2008-10-10 04:40:28,758 <WARN> [main] (CommonDAO.java:23) : Can not start transaciton
2008-10-10 04:40:28,759 <WARN> [main] (CommonDAO.java:24) : com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException: Connection.close() has already been called. Invalid operation in this state.
2008-10-10 04:40:28,759 <WARN> [main] (CommonDAO.java:63) : Can not rollback
2008-10-10 04:40:28,760 <WARN> [main] (CommonDAO.java:64) : com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException: Connection.close() has already been called. Invalid operation in this state.
2008-10-10 04:40:28,760 <WARN> [main] (CommonDAO.java:63) : Can not rollback
2008-10-10 04:40:28,760 <WARN> [main] (CommonDAO.java:64) : com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException: Connection.close() has already been called. Invalid operation in this state.
2008-10-10 04:40:28,760 <WARN> [main] (MultiThreadCrawler.java:231) : 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.io.EOFException

STACKTRACE:

java.io.EOFException
at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:1913)
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2304)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2803)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1573)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1665)
at com.mysql.jdbc.Connection.execSQL(Connection.java:3170)
at com.mysql.jdbc.Connection.rollbackNoChecks(Connection.java:5191)
at com.mysql.jdbc.Connection.rollback(Connection.java:5099)
at com.mnv.dao.CommonDAO.rollback(CommonDAO.java:53)
at com.mnv.core.crawlers.MultiThreadCrawler.startCrawler(MultiThreadCrawler.java:226)
at com.mnv.core.crawlers.mainentries.CrawlerMainEntry.crawlerMain(CrawlerMainEntry.java:53)
at com.mnv.core.crawlers.mainentries.Main.main(Main.java:26)


** END NESTED EXCEPTION **



Last packet sent to the server was 0 ms ago.

STACKTRACE:

com.mysql.jdbc.CommunicationsException: Communications link failure due to underlying exception:

** BEGIN NESTED EXCEPTION **

java.io.EOFException

STACKTRACE:

java.io.EOFException
at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:1913)
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2304)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2803)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1573)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1665)
at com.mysql.jdbc.Connection.execSQL(Connection.java:3170)
at com.mysql.jdbc.Connection.rollbackNoChecks(Connection.java:5191)
at com.mysql.jdbc.Connection.rollback(Connection.java:5099)
at com.mnv.dao.CommonDAO.rollback(CommonDAO.java:53)
at com.mnv.core.crawlers.MultiThreadCrawler.startCrawler(MultiThreadCrawler.java:226)
at com.mnv.core.crawlers.mainentries.CrawlerMainEntry.crawlerMain(CrawlerMainEntry.java:53)
at com.mnv.core.crawlers.mainentries.Main.main(Main.java:26)


** END NESTED EXCEPTION **



Last packet sent to the server was 0 ms ago.
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2515)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2803)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1573)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1665)
at com.mysql.jdbc.Connection.execSQL(Connection.java:3170)
at com.mysql.jdbc.Connection.rollbackNoChecks(Connection.java:5191)
at com.mysql.jdbc.Connection.rollback(Connection.java:5099)
at com.mnv.dao.CommonDAO.rollback(CommonDAO.java:53)
at com.mnv.core.crawlers.MultiThreadCrawler.startCrawler(MultiThreadCrawler.java:226)
at com.mnv.core.crawlers.mainentries.CrawlerMainEntry.crawlerMain(CrawlerMainEntry.java:53)
at com.mnv.core.crawlers.mainentries.Main.main(Main.java:26)


** END NESTED EXCEPTION **

说我在rollback前把连接关闭了...可是我关闭连接明明是在rollback后面啊.
...全文
1210 32 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
32 条回复
切换为时间正序
请发表友善的回复…
发表回复
shadowlin 2008-10-17
  • 打赏
  • 举报
回复
有没有谁也碰到这个问题的再来讨论下?
没有的话这两天就结贴了..hehe
shadowlin 2008-10-17
  • 打赏
  • 举报
回复
就目前查到的资料来看很可能是jdbc驱动的问题.
我查到些资料,解释了jdbc出现java.io.EOFException异常的可能情况.

[转自http://blogger.org.cn/blog/more.asp?name=NaddyLee&id=18795]
数据库换用mysql后,jboss在每天早上都要重启,查看后台,错误如下:
com.mysql.jdbc.CommunicationsException: Communications link failure due to underlying exception:

** BEGIN NESTED EXCEPTION **

java.io.EOFException

STACKTRACE:

java.io.EOFException
at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:1913)
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2304)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2803)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1573)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1665)
at com.mysql.jdbc.Connection.execSQL(Connection.java:3118)
at com.mysql.jdbc.Connection.setAutoCommit(Connection.java:5215)
at org.jboss.resource.adapter.jdbc.BaseWrapperManagedConnection.checkTransaction(BaseWrapperManagedConnection.java:425)
at org.jboss.resource.adapter.jdbc.WrappedConnection.checkTransaction(WrappedConnection.java:766)
at org.jboss.resource.adapter.jdbc.WrappedConnection.prepareStatement(WrappedConnection.java:214)
at org.hibernate.jdbc.AbstractBatcher.getPreparedStatement(AbstractBatcher.java:497)

……

这个问题是由于连接池中的连接失效引起的。

在 MySQL 的默认设置中,空闲超过 8 小时的连接会被自动关闭(interactive_timeout=28800,wait_timeout=28800)。

当连接池没有销毁掉空闲时间超过设置的连接,这些连接会因为已被数据库关闭而导致失效。
在原来的数据库连接池设置中,idle-timeout-minutes 的值设置为0(不销毁空闲连接),因此出现了在每天早上(空闲超过 8 小时),连接失效的情况。
在 Tomcat 的 Realm 设置中,有时也会出现这种情况(Realm 中没有设置 idle-timeout)。解决的方法是升级到 Tomcat 5.5.9 以上版本,并将 JDBCRealm 改为 DataSourceRealm。

还有一种情况 http://bugs.mysql.com/bug.php?id=14279 是在使用 XAConnections 的时候出现。是因为 mysql 的 JDBC 驱动在清理连接时,没有检查是否 XA 的 connection 就直接调用 rollback 引起的。出现这个问题的驱动是:mysql-connector-java-5.0-nightly-2005102。这个缺陷报告的状态已被设为关闭(已修复?)。


转自[http://gyc567.javaeye.com/blog/137422]
Hibernate用Mysql数据库时链接关闭异常的解决
在一个项目中,客户要求除操作系统外全部使用免费软件,因此我使用了Mysql 4.0作为数据库服务器,其JDBC驱动为3.0.9版本,在给客户安装后调试一切正常。可是到了第二天,只要一登录就提示“No operations allowed after connection closed”异常,显示在浏览器上。在经过一番检查后我发现,在这种情况下只要重新启动Tomcat就恢复正常,然而到了第二天问题依旧。

在网上查找一下,原来Mysql在经过8小时不使用后会自动关闭已打开的连接,摘录原文如下:

5.4. I have a servlet/application that works fine for a day, and then stops working overnight

MySQL closes connections after 8 hours of inactivity. You either need to use a connection pool that handles stale connections or use the "autoReconnect" parameter (see "Developing Applications with MySQL Connector/J").

Also, you should be catching SQLExceptions in your application and dealing with them, rather than propagating them all the way until your application exits, this is just good programming practice. MySQL Connector/J will set the SQLState (see java.sql.SQLException.getSQLState() in your APIDOCS) to "08S01" when it encounters network-connectivity issues during the processing of a query. Your application code should then attempt to re-connect to MySQL at this point.



在客户那边,晚上时间是不会有人使用这个系统的,就造成了系统中原先没有考虑到的这个情况。

为此我试验了三种方法:1、在数据库的url中加入autoReconnect=true;2、在每次调用getSession()方法时判断session.isClosed()是否为真,若为真则调用session.reconnect();3、在经过两天,事实证明前两种方法都不起作用的情况下,我在这个页面找到了第三种方法,即不使用Hibernate内置的连接池(Hibernate强烈推荐不使用但我以前一直在用),改用C3P0连接池,这个连接池会自动处理数据库连接被关闭的情况。要使用C3P0很简单,先从Hibernate里把c3p0-0.8.3.jar复制到项目的lib目录中,再在hibernate.properties里去掉hibernate.c3p0开头的那些属性的注释(使用缺省值或自己需要的数值),这样Hibernate就会自动使用C3P0代替内置的连接池了。到目前为止前面的问题没有再出现过。

以前对Hibernate警告不要使用内置连接池作产品用途没有太放在心上,这次是一个教训,所以不论从稳定还是性能的考虑,都应该选择相对更加成熟的连接池。


update:除了连接池的原因,原先写的HibernateDAO类也有问题,在有些情况下一个session会被多个请求反复使用,现在已改正。另外,c3p0这个名字不是星球大战里那个机器人么?
shadowlin 2008-10-17
  • 打赏
  • 举报
回复
to singedcat:
我当然知道这句话的遗产是因为rollback的时候connection已经close了...
但是我可以确定我逻辑上不会出现这种情况,而且这个程序以前也没出过这个异常.
shadowlin 2008-10-17
  • 打赏
  • 举报
回复
我试了先关闭connection在beginTransaction想看看会有什么结果.
报的异常是这样的..

2008-10-17 17:29:44,105 <WARN> [main] (CommonDAO.java:23) : Can not start transaciton
2008-10-17 17:29:44,120 <WARN> [main] (CommonDAO.java:24) : com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException: Connection.close() has already been called. Invalid operation in this state.
但是不会有
this state.
2008-10-10 04:40:28,758 <WARN> [main] (MultiThreadCrawler.java:231) : com.mysql.jdbc.CommunicationsException: Communications link failure due to underlying exception:

** BEGIN NESTED EXCEPTION **

java.io.EOFException

STACKTRACE:

java.io.EOFException
at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:1913)
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2304)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2803)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1573)
at com.mysql.jdbc.ServerPreparedStatement.serverExecute(ServerPreparedStatement.java:1169)
at com.mysql.jdbc.ServerPreparedStatement.executeInternal(ServerPreparedStatement.java:693)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1404)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1318)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1303)
at com.mnv.dao.MDBMovieDAO.saveOrUpdateMovie(MDBMovieDAO.java:68)
at com.mnv.core.crawlers.MultiThreadCrawler.startCrawler(MultiThreadCrawler.java:203)
at com.mnv.core.crawlers.mainentries.CrawlerMainEntry.crawlerMain(CrawlerMainEntry.java:53)
at com.mnv.core.crawlers.mainentries.Main.main(Main.java:26)


** END NESTED EXCEPTION **
这样的异常....
这是为什么呢?
mi19880803 2008-10-16
  • 打赏
  • 举报
回复
引用 14 楼 preferme 的回复:
谈谈我的理解。

楼主去查一下 movieDao.saveOrUpdateMovie(movie);
和resourceDao.saveOrUpdateResource(resource);
或者 resourceDao.commit();
和movieDao.commit();

这几个方法里面,有没有将connection关闭,

估计是在你的某个saveOrUpdate方法里面,操作完成后,将connection关闭了。

huoyin 2008-10-16
  • 打赏
  • 举报
回复
connection有可能是超时而失效的,所以并不一定是你用close方法关闭掉的。
shadowlin 2008-10-16
  • 打赏
  • 举报
回复
to huoyin:
恩..谢谢指出beginTransaction判断connection上不够严谨的地方.

但是我还是不知道为什么connection被关闭了,有可能是程序外部的原因么?
因为这个异常就出现过这么一次..

我的connection是在dao实例生成的时候建立的,结束在调用dao.close的时候结束.
感觉不应该会发生这种连接在不该结束的时候就结束的情况啊.
以梦为马 2008-10-16
  • 打赏
  • 举报
回复
Can not rollback
Connection.close() has already been called.
说得很清楚,在你准备rollback时Connection已经close了。

没看你写的代码,你自己对症找找代码中什么地方会出这样的问题。
shadowlin 2008-10-16
  • 打赏
  • 举报
回复
to huoyin
java.io.EOFException
什么情况连接sql会出现这个异常啊?
huoyin 2008-10-16
  • 打赏
  • 举报
回复
调用前最好用conn.isClosed()判断一下就可以了
shadowlin 2008-10-16
  • 打赏
  • 举报
回复
to huoyin:
那如果是因为timeout一类的问题导致的connection close的话有没有什么比较好的解决方法呢?
从异常中看不出来是什么原因么?只提示 connection is closed?
tianqiao1689 2008-10-15
  • 打赏
  • 举报
回复
大家都很帅,顶
huoyin 2008-10-15
  • 打赏
  • 举报
回复
public void beginTransaction(){
if (conn != null) { //将其改为if (conn != null && !conn.isClosed()) {会好一点
try {
conn.setAutoCommit(false);
} catch (SQLException e) {
logger.warn("Can not start transaciton");
logger.warn(e);
}
} else {
logger.warn("Please get connect first");
}
}
连接在执行到上面红色的地方已经被关闭掉了,所以log中打出Can not start transaciton。
java__king 2008-10-15
  • 打赏
  • 举报
回复
好多强人
shadowlin 2008-10-15
  • 打赏
  • 举报
回复
这个异常就出现过这么一次....后来和以前都没出现过...
所以很恶心..不知道是为什么..有谁知道有哪些可能么?
simonn88 2008-10-14
  • 打赏
  • 举报
回复
public void close(){
try{
conn.close();
conn = null; }catch(SQLException e){
logger.warn("Can not close connection");
logger.warn(e);
}

}

还有
movieDao.beginTransaction();
resourceDao.beginTransaction();
去掉其中一个
再看看还有没异常?
shadowlin 2008-10-13
  • 打赏
  • 举报
回复
问题是这个ioexception是谁抛出来的?
我把能catch的都catch了啊.
这个是我DAO的基类,大家帮看下有没什么问题?

package com.mnv.dao;

import java.sql.Connection;
import java.sql.SQLException;

import org.apache.log4j.Logger;




public class CommonDAO {
private static Logger logger=Logger.getLogger(CommonDAO.class);
protected Connection conn;

public CommonDAO() {
}

public void beginTransaction(){
if (conn != null) {
try {
conn.setAutoCommit(false);
} catch (SQLException e) {
logger.warn("Can not start transaciton");
logger.warn(e);
}
} else {
logger.warn("Please get connect first");
}
}

public void commit() {
try {
if (conn != null && !conn.getAutoCommit()) {
conn.commit();
conn.setAutoCommit(true);
} else {
if (conn == null) {
logger.warn("Please get connect first");
} else {
logger.warn("Please start transaction before commit");
}
}
} catch (SQLException e) {
logger.warn("Can not commit transaction");
logger.warn(e);
}
}

public void rollback() {
try {

if (conn != null && !conn.getAutoCommit()) {
conn.rollback();
conn.setAutoCommit(true);
} else {
if (conn == null) {
logger.warn("Please get connect first");
} else {
logger.warn("Please start transaction before rollback");
}
}
} catch (SQLException e) {
logger.warn("Can not rollback");
logger.warn(e);
}
}

public void close(){
try{
conn.close();
}catch(SQLException e){
logger.warn("Can not close connection");
logger.warn(e);
}

}

}
yami251139 2008-10-10
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 preferme 的回复:]
谈谈我的理解。

楼主去查一下 movieDao.saveOrUpdateMovie(movie);
和resourceDao.saveOrUpdateResource(resource);
或者 resourceDao.commit();
和movieDao.commit();

这几个方法里面,有没有将connection关闭,

估计是在你的某个saveOrUpdate方法里面,操作完成后,将connection关闭了。
[/Quote]
感觉是connection关闭了,具体哪里不清楚,如果没有配置错误的话
冰思雨 2008-10-10
  • 打赏
  • 举报
回复
谈谈我的理解。

楼主去查一下 movieDao.saveOrUpdateMovie(movie);
和resourceDao.saveOrUpdateResource(resource);
或者 resourceDao.commit();
和movieDao.commit();

这几个方法里面,有没有将connection关闭,

估计是在你的某个saveOrUpdate方法里面,操作完成后,将connection关闭了。


yami251139 2008-10-10
  • 打赏
  • 举报
回复
是没有rollback啊。。。
2008-10-10 04:40:28,708 <WARN> [main] (CommonDAO.java:63) : Can not rollback
2008-10-10 04:40:28,709 <WARN> [main] (CommonDAO.java:64) : com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException: Connection.close() has already been called. Invalid operation in this state.
这里就说了啊

可能是你的连接池有异常
也可能你的数据太大了没读好,或者驱动版本太低什么的
加载更多回复(12)

62,635

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧