从 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&characterEncoding=UTF-8&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/