Spring事务管理最容易犯的一种错误

此错误来自于实际项目中,所使用的解决方法在实际应用中证明是正确的。

 

项目背景:采用SSH架构,tomcat部署,apache负责集群,terracotta负责session共享。

 

在我们维护某项目的初期,当访问我们的web服务的用户数过多时,会出现apache的JK Status Manager中Busy数过高,当达到某一峰值,我这里遇到的Busy数是300左右时,对应tomcat将宕掉。

 

下面是我们在action个中使用事务的代码模板,我想通常大家也是这样用的吧。

 

DefaultTransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status = transactionManager.getTransaction(def);
try {
    ...

    transactionManager.commit(status);
    return SUCCESS;

} catch (Exception e) {
    ...
    transactionManager.rollback(status);
    return ERROR;
}

 

其实这里隐藏着一个很大的问题,即当try中有程序员使用“return ERROR;”语句跳出此程序段时,数据库已经接收到此事务,并将对应表锁住,等待提交或是回滚命令,但此时已无法执行到之后的“transactionManager.commit(status);”或是“transactionManager.rollback(status);”,当多用户应用本系统时,就很容易出现oracle锁等待的问题。

 

此处的解决办法是,在try{}代码段中,出现任何的return,都应根据return的性质,决定在此处是加入“transactionManager.commit(status);”还是加入“transactionManager.rollback(status);”,以确保不出现oracle锁等待的问题。

 

有时,我也发现有些程序员在try{}代码段中“transactionManager.commit(status);"之后,又对数据库进行了某些操作,才”return SUCCESS;“。我不建议这样做,程序员应该清楚此时的数据库操作自己是否要作为事务的一部分,这个问题是必须明确的。如果要作为事务的一部分,就应该放在“transactionManager.commit(status);"之前,如果不是作为事务的一部分,就应该放在整个事务处理之后,也就是上面catch{}完结之后。不然极易让人误读,不利于后期维护,关键也很容易让代码出错。

 

你可能感兴趣的:(事务,spring事务,oracle锁)