浏览 2500 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2013-07-17
最后修改:2013-07-17
问题:
CobarClient(https://github.com/alibaba/cobarclient 下面简称CC)在Spring2.5下的配置事务管理器 <bean id="transactionManager" class="com.alibaba.cobar.client.transaction.MultipleDataSourcesTransactionManager"> <property name="cobarDataSourceService" ref="dataSources" /> <property name="globalRollbackOnParticipationFailure" value="true" /> </bean> 但是在Spring3.x下面这样配置,在启动事务的时候,会有错误 java.lang.IllegalStateException: Cannot activate transaction synchronization - already active at org.springframework.transaction.support.TransactionSynchronizationManager.initSynchronization(TransactionSynchronizationManager.java:270) at org.springframework.transaction.support.AbstractPlatformTransactionManager.prepareSynchronization(AbstractPlatformTransactionManager.java:537) at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373) at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:417) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:255) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) at $Proxy10.createOffersInBatch(Unknown Source) at com.alibaba.cobar.client.transaction.MultipleDataSourcesTransactionManagerTest.testOfferCreationOnMultipleShardsWithNormallyOfferService(MultipleDataSourcesTransactionManagerTest.java:94) 检查原因: 启动事务的时候,TransactionManager会调用getTransaction方法初始化事务,这里面会调用子类的doBegin方法 而MultipleDataSourcesTransactionManager(CC实现的子类)的doBegin方法中将调用各个实际数据源DataSourceTransactionManager的getTransaction方法,从而开启各个数据源的事务 List<DefaultTransactionStatus> list = (List<DefaultTransactionStatus>) transactionObject; for (PlatformTransactionManager transactionManager : transactionManagers) { DefaultTransactionStatus element = (DefaultTransactionStatus) transactionManager .getTransaction(transactionDefinition); list.add(element); } ps:其实最好做法是调用各个实际数据源的doBegin方法,但是因为这个方法是protected的,无法在外部调用,只能退而求其次,调用getTransacation方法。 但是在新版spring下面,MultipleDataSourcesTransactionManager的抽象类AbstractPlatformTransactionManager进行了重写 getTransaction方法内部在调用doBegin之后又调用了prepareSynchronization方法 boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); DefaultTransactionStatus status = newTransactionStatus( definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); doBegin(transaction, definition); prepareSynchronization(status, definition); return status; 这个方法会调用initSynchronization初始化一个ThreadLocal变量synchronizations 在初始化之前会检查该变量是否已经初始化了,如果出现就报错。 而CC的doBegin是调用了getTransaction,所以该变量会初始化多次,所以导致无法通过检查。 protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) { if (status.isNewSynchronization()) { TransactionSynchronizationManager.setActualTransactionActive(status.hasTransaction()); TransactionSynchronizationManager.setCurrentTransactionIsolationLevel( (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) ? definition.getIsolationLevel() : null); TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly()); TransactionSynchronizationManager.setCurrentTransactionName(definition.getName()); TransactionSynchronizationManager.initSynchronization(); } } 但是如果我们把transactionManager 的transactionSynchronization设置为SYNCHRONIZATION_NEVER,就会避免initSynchronization重复初始化问题, 因为MultipleDataSourcesTransactionManager的isNewSynchronization属性为false,initSynchronization就不会执行。 Spring3.x中设置如下: <bean id="transactionManager" class="com.alibaba.cobar.client.transaction.MultipleDataSourcesTransactionManager"> <property name="cobarDataSourceService" ref="dataSources" /> <property name="transactionSynchronization" value="2" /> </bean> TransactionSynchronization的含义: 下面摘自网上的描述 TransactionSynchronization是可以注册到事务处理过程中的回调接口。它就像是事务处理的事件监听器,当事务处理的某些规定时点发生时,会调用TransactionSynchronization上的一些方法来执行相应的回调逻辑,如在事务完成后清理相应的系统资源等操作。Spring事务抽象框架所定义的TransactionSynchronization类似于JTA规范的javax.transaction.Synchronization,但比JTA的Synchronization提供了更多的回调方法,允许我们对事务的处理添加更多的回调逻辑。 具体我没有用过,我一直是使用默认的。 可能导致的问题: 个人分析-不会,因为我们屏蔽的只是CC的MultipleDataSourcesTransactionManager的transactionSynchronization属性,而实际的数据源事务管理器的transactionSynchronization仍然是默认的SYNCHRONIZATION_ALWAYS。 总结一下,可以这样认为,我们在CC中不支持transactionSynchronization特性。 其实我们对MultipleDataSourcesTransactionManager设置的属性都没有应用到的数据源事务管理器DataSourcesTransactionManager上 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |