作者·2010-02-09 10:49
·

WebSphere的DSRA9110E错误[藏]

字数 4173阅读 4281评论 0赞 0

    最近测试系统时遇到一个在并发压力下系统会生成重复“单号”的问题。

   “单号”是一次业务操作时产生的序列号(重要,必须唯一),格式如:KI100126000001KI为一类型号,100126为当天日期(年份取末2),后面是流水帐号,不足6位补0,每日重新从1开始。系统是使用struts + spring + hirbernate框架的,中间件是IBM WebSphere 6.1(Win2003平台),数据库为Sybase 15(AIX平台)

 生成单号的方法是:

    数据库中有一个SHIT_SERIALNO表,通过该表的序列号字段SERIAL_NO保存一个当前的流水帐号;

    由系统使用存储过程proc_shitNo来生成工单号。存储过程每次selectSERIAL_NO值,再Update SERIAL_NO值为SERIAL_NO+1,返回SERIAL_NO+1的值作为工单号的后一部分。

系统生成工单号后,将工单号的记录插入到一个SHIT_WORKSHIT的表,WORKSHIT_NO为唯一索引。

主要的问题是:

  10并发压力下,系统似乎会不断地获取到相同的序列号,生成重复的工单号从而使得插入数据失败。(据开发人员介绍,系统代码里会尝试进行10次插入操作,10次都不成功则在WAS的日志输出“保存10次工单依然无法保存”,每一次都是重新执行存储过程,重新生成单号)。插入数据失败的情况:2000笔业务大约是丢失30~70个单号记录。TPS值约在20~30之间。

    同一个生成工单的场景10并发压力时,对WAS服务器的CPU压力较大,CPU平均使用60~70%(这是优化了一段时间后的结果),数据库的压力较小。其它磁盘网络等未见有瓶颈或异常。


在保存单号失败时,WAS服务器记录的LOG如下:

26.1.2010 12:50:42 com.csair.callcenter.business.impl.WorksheetNoPrcoManagerImpl executeSPOfJndi
ERROR: ConnectionCallback; uncategorized SQLException for SQL []; SQL state [null]; error code [0]; DSRA9110E: 关闭 Connection。; nested exception is com.ibm.websphere.ce.cm.ObjectClosedException: DSRA9110E: 关闭 Connection。
org.springframework.jdbc.UncategorizedSQLException: ConnectionCallback; uncategorized SQLException for SQL []; SQL state [null]; error code [0]; DSRA9110E: 关闭 Connection。; nested exception is com.ibm.websphere.ce.cm.ObjectClosedException: DSRA9110E: 关闭 Connection。
 at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate

......

 at com.csair.callcenter.business.impl.WorksheetNoPrcoManagerImpl$1.doInConnection(WorksheetNoPrcoManagerImpl.java:55)
 at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:342)
 ... 59 more
[10-1-26 12:50:42:660 CST] 0000005f Batch         E org.directwebremoting.util.CommonsLoggingOutput error A request has been denied as a potential CSRF attack.
[10-1-26 12:50:42:660 CST] 00000069 SystemOut     O 26.1.2010 12:50:42 com.csair.callcenter.business.impl.WorksheetManagerImpl createWorksheet
ERROR: 保存单号失败
com.csair.callcenter.business.exception.BusinessException: 创建单号失败

......

[10-1-26 12:50:42:723 CST] 00000036 SystemOut     O 26.1.2010 12:50:42 com.csair.callcenter.business.impl.CallinManagerImpl startUpCallin
ERROR: 创建单号失败
com.csair.callcenter.business.exception.BusinessException: 保存10次单号依然无法保存

......

 

网上和同事分析造成DSRA9110E的原因一般是由于应用在执行数据库操作时jdbc数据库连接已经处于关闭状态。

但为什么系统正在运行时WebSphere的数据库连接会处于关闭状态呢?大家都不得其解!我一直以来很少做开发,压力测试时也不接触代码。而且一段时间下来,心烦气燥的,且在领导一日一报告的压力下,冷静分析理智思考的能力早失,嘿,不过似乎也一直未拥有过。

最后开发人员发现,系统代码中调用存储过程的方法前缺少了synchronized关键字来保证代码的线程安全,只需要在方法前添加一synchronized关键字即可。

 

这一问题算是解决了,但为何线程不安全会使应用在执行数据库操作时jdbc数据库连接已经处于关闭状态???

 

疯乱猜一下:10并发下,多次获取到重复单号并插入数据库失败,因为单号是唯一索引。每一个单号插入失败即会for循环生成10次并尝试插入。确定的30次丢失单号“保存10次单号依然无法保存”进行的保存操作是300次,另外的1970笔单号没有丢失,但无法确定它们是第一次生成就插入成功的,还是第9次尝试才生成单号并插入成功。如果计算取尝试平均值5,那就是9850次失败。哈,那插入操作进行了10150次才完成。呵呵,这样看来,部分连接处于关闭状态应该相应会较正常

    使用synchronized可以保证数据一致性问题,因为同一时间只有一个线程在执行,理论上会对性能有一定影响。但实际测试中,只生成单号场景10并发压力,使用synchronized关键字后,平均响应时间0.021秒,TPS平均值384.6;不使用synchronized关键字,平均响应时间0.172秒,TPS平均值43.8。原因分析为:不使用synchronized时,多次出现“保存10工单依然保存失败”的情况,可能大大增加了响应时间。 

 

  上面的修改过程中,使用过sybase官方的jdbc3驱动和第三方的jtds进行测试。在解决丢单问题后,面对更大压力(30并发)时,使用jtds驱动会偶尔出现如下错误:

[10-1-27 12:18:40:129 CST] 0000023a ConnectionEve A   J2CA0056I: 连接管理器接收到来自资源 jdbc/ccs_jtds 的资源适配器的致命连接错误。接收到的异常为 com.ibm.websphere.ce.cm.StaleConnectionException: There is not enough procedure cache to run this procedure, trigger, or SQL batch. Retry later, or ask your SA to reconfigure ASE with more procedure cache.
:java.sql.SQLException: There is not enough procedure cache to run this procedure, trigger, or SQL batch. Retry later, or ask your SA to reconfigure ASE with more procedure cache.

 而同等压力下使用jdbc3则无此现象,系统运行正常不会出现procedure cache不足的情况。是否可从某一侧面上表明使用sybase官方的驱动程序jdbc3比jtds在数据库内存消耗这一方面上更优?!哎,这种的证明真是麻烦。

原文地址:http://blog.sina.com.cn/s/blog_477759e70100gk6c.html

如果觉得我的文章对您有用,请点赞。您的支持将鼓励我继续创作!

0

添加新评论0 条评论

Ctrl+Enter 发表

作者其他文章

相关文章

相关问题

相关资料

X社区推广