背景:
XX系统实施一段时间之后,出现
数据库连接池满,第一次通过修改if(con!=null && con.isClosed()){con.close();}这样的逻辑
错误解决部分
问题。第二次通过彻底复查
代码,修改了connection、session没有释放的问题,基本上保证我们自己写的代码没有数据库连接不释放的问题。但是临近近期还是出现连接池满的问题。。。
过程:
从日志看,除了有大量工作流
报错之外程序很少有异常,类似如下:
引用:
2009-06-12 15:44:34,187 [http-80-Processor44] [org.hibernate.event.def.AbstractFlushingEventListener] [ERROR] - Could not synchronize database state with session
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [org.jbpm.graph.exe.Token#35000000000033432]
..............................................
at org.jbpm.persistence.db.DbPersistenceService.close(DbPersistenceService.java:180)
..............................................
2009-06-12 15:44:34,187 [http-80-Processor44] [org.jbpm.svc.Services] [ERROR] - problem closing service 'persistence'
org.jbpm.persistence.JbpmPersistenceException: couldn't flush hibernate session
at org.jbpm.persistence.db.DbPersistenceService.close(DbPersistenceService.java:182)
Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [org.jbpm.graph.exe.Token#35000000000033432]
at org.jbpm.persistence.db.DbPersistenceService.close(DbPersistenceService.java:180)
... 54 more
最开始基本确定了是工作流报错导致数据库连接池不释放,理由:
a、上面的错和hibernate的session有关
b、在
sybase执行sp_who发现大量不释放连接所占用的库为DB_LC,而这个库就是工作流相关的库。
c、从sybase的sysprocesses表查看,不释放连接是每天新增10-30不等,随机统计了日志某天的如前所述的异常为27个,而从数据库端统计该天新增连接也是27个。
因为自己对工作流不熟悉,所以每次都是把情况反映给相关人员处理。前几天去客户现场正好抓取了一下不释放连接正在执行的
sql,基本都是
乱码,如下:
引用:
DBCC execution completed. If DBCC printed error messages, contact a user with System Administrator (SA) role.
SQL Text: !
DBCC execution completed. If DBCC printed error messages, contact a user with System Administrator (SA) role.
(1 row affected)
47
DBCC execution completed. If DBCC printed error messages, contact a user with System Administrator (SA) role.
SQL Text: *
DBCC execution completed. If DBCC printed error messages, contact a user with System Administrator (SA) role.
(1 row affected)
49
DBCC execution completed. If DBCC printed error messages, contact a user with System Administrator (SA) role.
SQL Text:
DBCC execution completed. If DBCC printed error messages, contact a user with System Administrator (SA) role.
(1 row affected)
这个结果用处不大,很好奇这个问题,所以找了一份工作流的源码,找到报错的类DbPersistenceService.close方法,如下:
复制内容到剪贴板
代码:
public void close() {
if ( (session!=null)
&& (transaction==null)
&& (isRollbackOnly)
) {
throw new JbpmException("setRollbackOnly was invoked while configuration specifies user managed transactions");
}
if (messagingSession!=null) {
messagingSession.closeOpenIterators();
}
if (schedulerSession!=null) {
schedulerSession.closeOpenIterators();
}
if ( (isTransactionEnabled)
&& (transaction!=null)
) {
if (isRollbackOnly) {
try {
log.debug("rolling back hibernate transaction");
mustSessionBeFlushed = false; // flushing updates that will be rolled back is not very clever :-)
transaction.rollback();
} catch (Exception e) {
throw new JbpmPersistenceException("couldn't rollback hibernate session", e);
}
} else {
try {
log.debug("committing hibernate transaction");
mustSessionBeFlushed = false; // commit does a flush anyway
transaction.commit();
} catch (Exception e) {
try {
// if the commit fails, we must do a rollback
transaction.rollback();
} catch (Exception e2) {
// if the rollback fails, we did what we could and you're in
// deep shit :-(
log.error("problem rolling back after failed commit", e2);
}
throw new JbpmPersistenceException("couldn't commit hibernate session", e);
}
}
}
if (mustSessionBeFlushed) {
try {
log.debug("flushing hibernate session");
session.flush();
} catch (Exception e) {
throw new JbpmPersistenceException("couldn't flush hibernate session", e);
}
}
if (mustSessionBeClosed) {
try {
log.debug("closing hibernate session");
session.close();
} catch (Exception e) {
throw new JbpmPersistenceException("couldn't close hibernate session", e);
}
}
if (mustConnectionBeClosed) {
try {
log.debug("closing jdbc connection");
connection.close();
} catch (Exception e) {
throw new JbpmPersistenceException("couldn't close jdbc connection", e);
}
}
}
一看真是吓一跳,程序在执行到session.flush();时候报错的话,如果mustSessionBeClosed为true根本不能执行到后面的session.close(),会导致数据库连接不释放的问题……基本确定问题所在了,就在本地试着复现一下问题(因为前面所描述的异常在
开发环境无法复现,所以只能强制在flush后抛异常),果然不出意料。
因为这个是jbpm3.1.2版本,觉得应该是jbpm的
bug吧,就又下载了一份jbpm3.3.0GA源码,找到DbPersistenceService.close()方法:
复制内容到剪贴板
代码:
public void close() {
if ( (session!=null)
&& !isTransactionActive()
&& (isRollbackOnly())
) {
throw new JbpmException("setRollbackOnly was invoked while configuration specifies user managed transactions");
}
if ( (isTransactionEnabled)
&& (transaction!=null)
) {
if (! isRollbackOnly()) {
Exception commitException = commit();
if (commitException!=null) {
rollback();
closeSession();
closeConnection();
throw new JbpmPersistenceException("hibernate commit failed", commitException);
}
} else { // isRollbackOnly==true
Exception rollbackException = rollback();
if (rollbackException!=null) {
closeSession();
closeConnection();
throw new JbpmPersistenceException("hibernate rollback failed", rollbackException);
}
}
}
Exception flushException = flushSession();
if (flushException!=null) {
// JBPM-1465 transaction has been either committed or rolled back at this point
// on the other hand, it is possible that no transaction is underway
// hence rolling back here is redundant and possibly dangerous
closeSession();
closeConnection();
throw new JbpmPersistenceException("hibernate flush failed", flushException);
}
Exception closeSessionException = closeSession();
if (closeSessionException!=null) {
closeConnection();
throw new JbpmPersistenceException("hibernate close session failed", closeSessionException);
}
Exception closeConnectionException = closeConnection();
if (closeConnectionException!=null) {
throw new JbpmPersistenceException("hibernate close connection failed", closeConnectionException);
}
}
果然在3.3.0版本中,当flush、close等操作出现异常时候,都会调用closeSession()和closeConnection()以保证连接正常释放。照猫画虎在该方法写了关闭session和connection的方法,准备月底发布新版本试试。
结论:
XX系统工作流jbpm3.1.2存在连接不释放的bug,当然前提是程序执行数据库操作报错的情况下(如session.flush)。虽然解决了连接不释放的问题,但是这个关于这个报错的深层原因还没搞清楚。另外和相关人员确认,工作流的这些异常可以cacth掉,到目前为止除了引起连接不释放之外,没有发现其他问题。
分享到:
相关推荐
jbpm3.1.2_webapp jar包齐全 使用oracle10g数据库
jBpm是一个灵活可扩展的工作流管理系统。作为jBpm运行时server输入的业务流程使用简单强大的语言表达并打包在流程档案中
jbpm 数据库jbpm 数据库jbpm 数据库jbpm 数据库jbpm 数据库
jbpm创建数据库jbpm创建数据库jbpm创建数据库jbpm创建数据库jbpm创建数据库jbpm创建数据库jbpm创建数据库jbpm创建数据库jbpm创建数据库
jbpm-webapp-3.1.2.jar
对JBPM开源工作流的研究,主要对JBPM的内部构造进行了解,包括流程驱动机制即TOKEN机制、事件模型、数据库结构以及表之间的关系。 对JBPM工作流进行二次开发,主要包括对JBPM功能的扩展、流程定义工具、流程...
如何将原有的H2数据库修改为指向mysql或者postgresql数据库。附实例
NULL 博文链接:https://hxyt20.iteye.com/blog/659880
jbpm-3.1.2.jar jar jbpm
JBPM4.4 mysql数据库创建脚本,修正ant create.jbpm.schema不能创建数据库的bug。
jBPM工作流详解,jBPM工作流详解 jBPM工作流详解,jBPM工作流详解 jBPM工作流详解,jBPM工作流详解
JBPM + SSH 相关JAR JPBM WEB开发
工作流程 JBPM工作流管理工作流程 JBPM工作流管理工作流程 JBPM工作流管理工作流程 JBPM工作流管理
关于jbpm工作流的一些常用的问题jbpm工作流的一些常用的问题
工作流设计参考(包括 PHP 实现) 本文关键词: php 工作流,workflow 工作流设计的工作流很少有让人满意的,即便是国内用的比较多的 jbpm,用起来也会 觉得很便扭。再加上 PHP 中没有什么好用的工作流,于是干脆自己...
jbpm4.4 DB2数据库脚本,可直接执行sql脚本,创建jbpm4.4 数据库表
ssh-jbpm可以运行的工作流,其中的包去下载我的struts2.0+spring2.0+hibernate3.0所需要的包和struts2.0+spring2.0+hibernate3.0中加入jbpm3.1.2所需要的包
jbpm工作流引擎基于J2EE的轻量级,纯java,开源的工作流管理系统。
1 ACTIVITI数据库表结构 2 1.1 数据库表名说明 2 1.2 数据库表结构 3 1.2.1 Activiti数据表清单: 3 1.2.2 表名:ACT_GE_BYTEARRAY (通用的流程定义和流程资源) 3 1.2.3 表名:ACT_GE_PROPERTY (系统相关属性) 4 ...
eclipse工作流插件 含jBPM_4.4_开发指南eclipse工作流插件 含jBPM_4.4_开发指南eclipse工作流插件 含jBPM_4.4_开发指南