首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > Web前端 >

websphere上报DSRA9350E有关问题一例

2012-08-31 
websphere下报DSRA9350E问题一例近期在项目中发现一个很奇怪的问题。项目在做集成测试和功能测试时一切正常

websphere下报DSRA9350E问题一例
近期在项目中发现一个很奇怪的问题。项目在做集成测试和功能测试时一切正常,可在上线后却总是报DSRA9350E: Operation setAutoCommit is not allowed during a global transaction.的错误。着实让我们费解了一把。

首先,一通google,发现这个问题会在受管全局数据源中使用Connection.setAutoCommit方法时出现,也就是说,如果你的代码中使用了全局的事务,如JTA,并在JTA事务生命周期内调用那个方法时,就会导致这个问题。

既然有了切入点,那就开始调查了。经过调查,发现这个错误总是出现在一个message bean中。于是继续深入,发现该message bean的onMessage方法中有这样一段代码:

       ...........................userTran = messageDrivenCtx.getUserTransaction();userTran.begin();doProcess();   ............................
    

而在doProcess()方法中又主要做了这样的事情

..............................processor.process(processorMsg);userTran.commit();................................


于是乎进一步深入调查,发现在做processor.process()的整个过程中,存在调用数据库的问题,并且还使用了Connection.setAutoCommit(boolean)方法。所以导致出现了这个问题。既然问题找到,我们就做了相应更改。由于访问数据库是前人写的一些数据库访问层的封装,不好做更改,于是乎我们只好将JTA相关的部分更改,即在message bean里去掉了JTA方式的事务控制。然后在生产环境中部署,问题解决,皆大欢喜。

问题解决后,自然是问题总结和事后分析阶段。我们在这里所碰到的最大困扰就是:同样的代码,为什么部署在测试环境没有问题,却在生产环境出现问题呢? 难道是两个环境下的WEBSPHERE设置存在差异?或数据库设置存在差异? 带着这两个问题, 我们去检查了这些环境,但却发现虽然存在一定的差异,但却并不是会导致这个问题产生的根本原因。

既然不是环境问题,那就只可能是我们的代码所导致的问题了。我们首先从那个数据库封装层下手,发现这个封装层提供了两种方式来访问数据源,一种是使用websphere的数据库连接池,另一种就是直接的DriverManager方式。在实际运行阶段,它会首先通过JNDI去访问数据源,如果发生异常(如JNDI错误或数据源不存在),则会自动切换到DriverManager方式。于是乎这里就成了我们的怀疑点:是否在测试环境使用的是DriverManager而生产环境却使用了数据源pool? 为了确认这点, 我们添加了一些log语句并在两个环境中运行程序。结果证实了我们的猜想。

既然这样,我们就从数据源出发继续探查,发现在测试环境中,我们之前在项目中新建了一个数据库并新建了对应的数据源与之对应。但由于生产环境不允许更改,我们只对旧有的数据库做了扩充,并没有新建数据库和数据源。之前的代码中,数据源JNDI是被添加进message bean的context中的, 但在测试环境中,新添加的数据源JNDI却由于疏忽,忘记被添加进message bean的context中去,直接导致了两个环境使用数据库访问方式的差异。后来我们将其修正后,放入测试环境中,果然重现了那个问题。

针对这次问题,我们得到了一些教训,总结如下:
1.不要混合使用全局事务和数据库事务,容易导致此类问题的发生。
2.如果要在EJB中使用一些资源引用(如数据源或其他EJB),一定记住将该资源添加进该EJB的上下文环境中,否则会导致无法引用(似乎是废话,但确实经常被一些程序员忘记)
3.log的重要性啊。。。。。。。

热点排行