Jboss 7.2 txn管理到Spring管理的PlatformTransactionManager-锁定表

问题描述 投票:2回答:1

从JBoss容器管理的TransactionManagement迁移到Spring管理的事务管理器-(死)将插入时的表锁定到表,并且不关闭txn / session,并且从应用程序跟踪txns也会得到相同的错误。仅在使用PlatformTransactionManager之后,并且在其中一个jvm / appserver在0s间隔上选择该表,而另一个jvm / appserver在同一表上运行insert并插入txn挂起的情况下,此行为才发生。我必须杀死txn show full PROCESSLIST; kill <pid>;才能释放锁,以便下一个sql可以继续。

任何帮助/提示,​​我们感激不尽。

Caused by: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
        at [email protected]//com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:123)
        at [email protected]//com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
        at [email protected]//com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
        at [email protected]//com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:955)
        at [email protected]//com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1094)
        at [email protected]//com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1042)
        at [email protected]//com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1345)
        at [email protected]//com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:1027)
        at [email protected]//org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.executeUpdate(WrappedPreparedStatement.java:537)
        at [email protected]//org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:175)

数据源:

<datasource jndi-name="java:jboss/datasources/my-ds" pool-name="my-ds" enabled="true" use-ccm="true" statistics-enabled="true">
                    <connection-url>jdbc:mysql://XXXXXXXXXXXX:3306/dbName?useSSL=false&amp;characterEncoding=UTF-8&amp;serverTimezone=US/Eastern</connection-url>
                    <driver>mysql</driver>
                    <pool>
                        <min-pool-size>1</min-pool-size>
                        <max-pool-size>10</max-pool-size>
                        <flush-strategy>FailingConnectionOnly</flush-strategy>
                    </pool>
                    <security>
                        <user-name>user</user-name>
                        <password>password</password>
                    </security>
                    <validation>
                        <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLValidConnectionChecker"/>
                        <check-valid-connection-sql>select 1 from dual</check-valid-connection-sql>
                        <validate-on-match>false</validate-on-match>
                        <background-validation>true</background-validation>
                        <background-validation-millis>30000</background-validation-millis>
                        <use-fast-fail>false</use-fast-fail>
                        <exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLExceptionSorter"/>
                    </validation>
                    <timeout>
                        <set-tx-query-timeout>false</set-tx-query-timeout>
                        <idle-timeout-minutes>10</idle-timeout-minutes>
                        <query-timeout>0</query-timeout>
                        <allocation-retry>3</allocation-retry>
                        <allocation-retry-wait-millis>2500</allocation-retry-wait-millis>
                    </timeout>
                </datasource>
                <drivers>
                    <driver name="oracle" module="com.oracle">
                        <xa-datasource-class>oracle.jdbc.xa.client.OracleXADataSource</xa-datasource-class>
                    </driver>
                    <driver name="mysql" module="com.mysql">
                        <xa-datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</xa-datasource-class>
                    </driver>
                </drivers>

persistence.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
     http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd"
             version="2.2">

    <persistence-unit name="unitName" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <non-jta-data-source>java:jboss/datasources/my-ds</non-jta-data-source>
        <class>com.company.entity1</class>
        <class>com.company.entity2</class>
        <class>com.company.entity3</class>
...
        <properties>
            <property name="jboss.as.jpa.managed" value="false"/>
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
            <property name="hibernate.show_sql" value="false"/>
            <property name="hibernate.generate_statistics" value="false"/>
            <property name="hibernate.id.new_generator_mapping" value="true"/>
            <property name="org.hibernate.envers.audit_table_suffix" value="_history"/>
            <property name="org.hibernate.envers.revision_field_name" value="history_info_id"/>
            <property name="org.hibernate.envers.revision_type_field_name" value="history_info_type"/>
        </properties>

    </persistence-unit>
    @Configuration
public class JpaConfig {

    @Bean
    public PersistenceUnitManager persistenceUnitManager() {
        DefaultPersistenceUnitManager persistenceUnitManager = new DefaultPersistenceUnitManager();
        persistenceUnitManager.setPersistenceXmlLocations("classpath*:META-INF/persistence.xml");
        persistenceUnitManager.setDataSourceLookup(new JndiDataSourceLookup());
        return persistenceUnitManager;
    }

    @Primary
    @Bean("someEntityManagerFactory")
    public EntityManagerFactory somentityManagerFactory(PersistenceUnitManager persistenceUnitManager) {
        LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactoryBean.setPersistenceXmlLocation("classpath*:META-INF/persistence.xml");
        entityManagerFactoryBean.setPersistenceUnitManager(persistenceUnitManager);
        entityManagerFactoryBean.setPersistenceUnitName("unitName");
        entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
        entityManagerFactoryBean.afterPropertiesSet();
        return entityManagerFactoryBean.getObject();
    }

    @Bean("someJpaTransactionManager")
    public PlatformTransactionManager someJpaTransactionManager(
            @Qualifier("someEntityManagerFactory") EntityManagerFactory entityManagerFactory){
        JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
        jpaTransactionManager.setEntityManagerFactory(entityManagerFactory);
        jpaTransactionManager.afterPropertiesSet();
        return jpaTransactionManager;
    }

TransactionStatus:

public static TransactionStatus getTransactionStatus(PlatformTransactionManager platformTransactionManager){
        DefaultTransactionDefinition txDef = new DefaultTransactionDefinition(PROPAGATION_REQUIRES_NEW);
        txDef.setTimeout(transactionTimeout.get().intValue());
        return platformTransactionManager.getTransaction(txDef);
    }

//Usage: jpaTransactionManager.commit(txnStatus);

标签:spring-tx,PlatformTransactionManager,spring-5.1.5

spring jboss spring-data jboss7.x
1个回答
1
投票

这可能有帮助

注释类型启用事务管理

@Target(value=TYPE)
 @Retention(value=RUNTIME)
 @Documented
 @Import(value=TransactionManagementConfigurationSelector.class)

public @interface EnableTransactionManagement启用S​​pring的注释驱动的事务管理功能,类似于Spring的XML名称空间中的支持。将在@Configuration类上使用,如下所示:

 @Configuration
 @EnableTransactionManagement
 public class AppConfig {

     @Bean
     public FooRepository fooRepository() {
         // configure and return a class having @Transactional methods
         return new JdbcFooRepository(dataSource());
     }

     @Bean
     public DataSource dataSource() {
         // configure and return the necessary JDBC DataSource
     }

     @Bean
     public PlatformTransactionManager txManager() {
         return new DataSourceTransactionManager(dataSource());
     }
 }

作为参考,可以将以上示例与以下Spring XML配置进行比较:

 <beans>

     <tx:annotation-driven/>

     <bean id="fooRepository" class="com.foo.JdbcFooRepository">
         <constructor-arg ref="dataSource"/>
     </bean>

     <bean id="dataSource" class="com.vendor.VendorDataSource"/>

     <bean id="transactionManager" class="org.sfwk...DataSourceTransactionManager">
         <constructor-arg ref="dataSource"/>
     </bean>

 </beans>

在以上两种情况下,@EnableTransactionManagement并负责注册必要的Spring组件,这些组件为注释驱动的事务管理提供支持,例如TransactionInterceptor和基于代理或基于AspectJ的建议,这些建议将拦截器编织到调用堆栈中。调用JdbcFooRepository的@Transactional方法。这两个示例之间的微小区别在于PlatformTransactionManager bean的命名:在@Bean情况下,名称为“ txManager”(按方法的名称);在XML情况下,名称为“ transactionManager”。在默认情况下,很难找到名称为“ transactionManager”的Bean,但是@EnableTransactionManagement更灵活。它将退回到容器中任何PlatformTransactionManager bean的按类型查找。因此,名称可以是“ txManager”,“ transactionManager”或“ tm”:没关系。

对于那些希望在@EnableTransactionManagement和要使用的确切事务管理器bean之间建立更直接关系的人,可以实现TransactionManagementConfigurer回调接口-请注意下面的Implements子句和@ Override-annotated方法:

@Configuration
 @EnableTransactionManagement
 public class AppConfig implements TransactionManagementConfigurer {

     @Bean
     public FooRepository fooRepository() {
         // configure and return a class having @Transactional methods
         return new JdbcFooRepository(dataSource());
     }

     @Bean
     public DataSource dataSource() {
         // configure and return the necessary JDBC DataSource
     }

     @Bean
     public PlatformTransactionManager txManager() {
         return new DataSourceTransactionManager(dataSource());
     }

     @Override
     public PlatformTransactionManager annotationDrivenTransactionManager() {
         return txManager();
     }
 }

此方法可能仅因为它更明确,否则可能是合乎需要的,或者可能有必要在同一个容器中区分两个PlatformTransactionManager bean。顾名思义,annotationDrivenTransactionManager()将用于处理@Transactional方法。有关更多详细信息,请参见TransactionManagementConfigurer Javadoc。mode()属性控制如何应用建议:如果模式为AdviceMode.PROXY(默认设置),则其他属性控制代理的行为。请注意,代理模式仅允许通过代理拦截呼叫。同一类内的本地调用无法以这种方式被拦截。

注意,如果将mode()设置为AdviceMode.ASPECTJ,则proxyTargetClass()属性的值将被忽略。还要注意,在这种情况下,spring-aspects模块JAR必须存在于类路径中,并使用编译时编织或加载时编织将方面应用于受影响的类。在这种情况下不涉及任何代理;本地电话也会被拦截。

© www.soinside.com 2019 - 2024. All rights reserved.