我有一个非常奇怪的错误使用Spring JPA事务。该线程被锁定大约16分钟,然后继续没有任何问题。打开新的EntityManager后线程锁定
这里的情况是:
@Transactional(propagation = Propagation.REQUIRES_NEW)
public class A {
public String encrypt(String str){
LOG.debug("encrypting...");
// just data base read operations
}
public String encrypt(String str, String str2){
// read and write database operations.
}
public String foo(...){
// read and write database operations.
}
public String bar(...){
// read and write database operations.
}
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public class B {
public String doSomething(...){
LOG.debug("calling encrypt method...");
String chain1 = this.a.encrypt("whatever");
LOG.debug("calling encrypt method...");
String chain2 = this.a.encrypt("again");
LOG.debug("calling encrypt method...");
String chain3 = this.a.encrypt("and again");
...
}
}
纵观日志文件中我看到,它需要16分钟内由日志“呼吁加密方法”,以“encripting”。因此,已启动JTA日志,这是我所看到的:
15:09:04.317 DEBUG e.i.n.p.d.TipoMensajeDaoDelegate [45] - obteniendo mensaje para tipo operacion 0104 y protocolo 03
15:09:04.318 DEBUG o.s.orm.jpa.JpaTransactionManager [332] - Found thread-bound EntityManager [[email protected]] for JPA transaction
15:09:04.319 DEBUG o.s.orm.jpa.JpaTransactionManager [471] - Participating in existing transaction
15:09:04.320 DEBUG o.s.orm.jpa.JpaTransactionManager [332] - Found thread-bound EntityManager [[email protected]] for JPA transaction
15:09:04.321 DEBUG o.s.orm.jpa.JpaTransactionManager [471] - Participating in existing transaction
15:09:04.324 DEBUG e.i.n.c.p.p.b.B [485] - calling encrypt method...
15:09:04.325 DEBUG o.s.orm.jpa.JpaTransactionManager [332] - Found thread-bound EntityManager [[email protected]] for JPA transaction
15:09:04.326 DEBUG o.s.orm.jpa.JpaTransactionManager [416] - Suspending current transaction, creating new transaction with name [es.indra.nnp.gestorclaves.GestorClavesServiceImpl.cifrar]
15:09:04.326 DEBUG o.s.orm.jpa.JpaTransactionManager [369] - Opened new EntityManager [[email protected]] for JPA transaction
...
15:24:29.954 DEBUG o.s.orm.jpa.JpaTransactionManager [408] - Not exposing JPA transaction [[email protected]] as JDBC transaction because JpaDialect [[email protected]] does not support JDBC Connection retrieval
15:24:29.955 DEBUG e.i.n.g.A [146] - encrypting
15:24:29.956 DEBUG o.s.orm.jpa.JpaTransactionManager [332] - Found thread-bound EntityManager [[email protected]] for JPA transaction
15:24:29.957 DEBUG o.s.orm.jpa.JpaTransactionManager [471] - Participating in existing transaction
15:24:29.958 DEBUG o.s.orm.jpa.JpaTransactionManager [332] - Found thread-bound EntityManager [[email protected]] for JPA transaction
15:24:29.958 DEBUG o.s.orm.jpa.JpaTransactionManager [471] - Participating in existing transaction
15:24:29.962 DEBUG o.s.orm.jpa.JpaTransactionManager [332] - Found thread-bound EntityManager [[email protected]] for JPA transaction
15:24:29.962 DEBUG o.s.orm.jpa.JpaTransactionManager [471] - Participating in existing transaction
...
这里,事实:
- 错误并不总是发生,但是当它总是在同一个点。
- 经过16分钟或多或少,线程继续并几次调用相同的方法,没有问题并正确完成。
- 当它发生时,它总是在15分30秒左右。
- 它发生没有并发。无论如何,当一个线程被锁定,如果我启动另一个线程没有问题。第二个线程在第一个线程仍处于锁定状态时处理。
- 正在检查DDBB是否在锁定期间查找数据库锁定。没有发现数据库锁。
- 其他方法形式类A从代码的其他点调用没有问题。
- 刚刚发生在生产环境中。你可以想象做改变有多困难。
- 数据库连接通过JNDI完成,MySql和应用程序在Tomcat中运行。
我知道用这些信息很难找出问题所在。只是我希望有人能够提供一些帮助我找到正在发生的事情的想法。
感谢您的贡献。没有定义事务超时,所以我们正在使用默认值(-1)。另外,认为它不能解释为什么它不会总是发生。我必须找出16个来自哪里,我认为这是关键。 – jddsantaella
它是否复制,而不是需要新的您需要? –
我没有测试它。我们正在一个PCI-DSS生产环境中工作,因此修改变得非常复杂。我所做的是在课堂级别移除交易,并仅在需要的方法中对其进行定义。由于“加密”方法不需要交易,所以希望我们不要再次面对错误。让我们来看看。我会尝试在其他环境中重现错误(如果我很幸运)并测试您的想法。 – jddsantaella