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

标签 mysql spring jboss jboss7.x spring-transactions

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

已锁定表的 MySQL 查询状态为 "Sending to client

Sending to client

The server is writing a packet to the client.

感谢任何帮助/提示。

Caused by: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
        at <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="92f1fdffbcffebe1e3fed2aabca2bca3a4" rel="noreferrer noopener nofollow">[email protected]</a>//com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:123)
        at <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e3808c8ecd8e9a90928fa3dbcdd3cdd2d5" rel="noreferrer noopener nofollow">[email protected]</a>//com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
        at <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="85e6eae8abe8fcf6f4e9c5bdabb5abb4b3" rel="noreferrer noopener nofollow">[email protected]</a>//com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
        at <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e4878b89ca899d979588a4dccad4cad5d2" rel="noreferrer noopener nofollow">[email protected]</a>//com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:955)
        at <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c9aaa6a4e7a4b0bab8a589f1e7f9e7f8ff" rel="noreferrer noopener nofollow">[email protected]</a>//com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1094)
        at <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="61020e0c4f0c1812100d21594f514f5057" rel="noreferrer noopener nofollow">[email protected]</a>//com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1042)
        at <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="f5969a98db988c868499b5cddbc5dbc4c3" rel="noreferrer noopener nofollow">[email protected]</a>//com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1345)
        at <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="5b383436753622282a371b63756b756a6d" rel="noreferrer noopener nofollow">[email protected]</a>//com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:1027)
        at <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="325d40551c58505d41411c5b405d5c585351535f53401c58565051535653424657404172031c061c03031c745b5c535e1f4057565a53461f0202020203" rel="noreferrer noopener nofollow">[email protected]</a>//org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.executeUpdate(WrappedPreparedStatement.java:537)
        at <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="8de2ffeaa3e5e4efe8ffe3ecf9e8cdb8a3bea3baa3cbe4e3ece1a0ffe8e9e5ecf9a0bdbdbdbdbc" rel="noreferrer noopener nofollow">[email protected]</a>//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>

持久性.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;
    }

交易状态:

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

最佳答案

this might help

注释类型启用事务管理

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

公共(public)@interface启​​用事务管理 启用 Spring 的注释驱动的事务管理功能,类似于 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”(根据方法的名称);在 @Bean 的情况下,名称是“txManager”(根据方法的名称);在 XML 情况下,名称为“transactionManager”。默认情况下,它是硬连线寻找名为“transactionManager”的 bean,但是 @EnableTransactionManagement 更灵活;它将回退到按类型查找容器中的任何 PlatformTransactionManager bean。因此,名称可以是“txManager”、“transactionManager”或“tm”:这并不重要。

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

@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 必须存在于类路径中,并且编译时编织或加载时编织将切面应用于受影响的类。这种情况下不涉及代理;本地调用也会被拦截。

关于mysql - Jboss 7.2 txn管理到spring管理的PlatformTransactionManager - 锁定表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59293823/

相关文章:

java - GlassFish - 非法状态异常

java - 如何在Jboss中使用连接池

java - JBoss 7.1 支持状态?

mysql - 如何在 ruby​​ on Rails 中将数据库(转储文件)从 mysql 数据库导出到 sqlite

mySQL "Unknown column"错误

java - Class.forName(JDBC_DRIVER);当代码相同时,仅在我的 2 个程序中的 1 个中工作。为什么?

java - Spring @Transactional 在类上与在方法上

php - mysql脚本自动停止

java - 等待服务返回的坏习惯?

java - 无法发送邮件 - javax.net.ssl.SSLException : Unrecognized SSL message, 纯文本连接?