교착 상태 문제가 있으며 어떻게 처리 할 수 있는지 알 수 없습니다. glassfish 서버에서 JPA 2.1 (eclipselink 포함)을 사용하고 있습니다.@TransactionAttribute (TransactionAttributeType.REQUIRES_NEW)로 JPA 교착 상태가 발생했습니다. 내 애플리케이션에
두 개의 EJB가 있습니다. OuterBean
은 LogEntry
을 데이터베이스에 쓰고 루프에서 InnerBean
을 호출해야합니다. InnerBean
그 자체 은 LogEntry
을 쓰고 다른 것들 (다른 엔티티에서 더 많은 데이터베이스 조작)을해야합니다. InnerBean#execute()
의 호출은 서로 독립적이므로 한 방법이 실패하면 (롤백) 나머지는 계속 실행해야합니다. 따라서 InnerBean#execute()
은 자체 트랜잭션으로 실행됩니다.
내가 MySQL을 아래 java.sql.SQLException: Lock wait timeout exeeded; try restarting transaction
오라클 아래 java.sql.SQLSyntaxErrorException: ORA-02049: timeout: distributed transaction waiting for lock
를 얻을 수 아래의 코드를 실행
저는 데이터베이스/JPA 전문가가 아니지만 두 트랜잭션이 동일한 데이터 테이블에 쓰기를 원한다고 생각합니다. 내가하지 않는 것 이 데이터베이스 조작은 각각 다른 기타와 독립적이어야하는 삽입이라는 점에서 문제가 있다는 것을 이해합니다. 이 유스 케이스를 구현할 수있는 방법이 있습니까 (Bean 관리 트랜잭션을 사용해야합니까, 사용할 수있는 주석이 있습니까, em.persist (logEntry) 이후에 OuterBean#execute()
에 커밋을 적용 할 수 있습니까?) 트랜잭션 잠금은 아무렇게나 해제됩니다)? 여기
EDIT
@Stateless
public class InnerBean
{
@PersistenceContext(unitName = "PU_LOGGER")
private EntityManager em;
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void execute()
{
LogEntry logEntry = new LogEntry();
logEntry.setDate(new Date());
logEntry.setMessage("InnerBean#execute()" + Math.random());
em.persist(logEntry);
}
}
@Stateless
public class OuterBean
{
@PersistenceContext(unitName = "PU_LOGGER")
private EntityManager em;
@EJB
private InnerBean innerBean;
public void execute()
{
LogEntry logEntry = new LogEntry();
logEntry.setDate(new Date());
logEntry.setMessage("OuterBean#execute()");
em.persist(logEntry);
for(int i = 0; i < 10; ++i)
{
innerBean.execute();
}
}
}
는 I 문제점을 해결 한
FINER: client acquired: 1990452734
FINER: TX binding to tx mgr, status=STATUS_ACTIVE
FINER: acquire unit of work: 38847372
FINEST: persist() operation called on: LogEntry{id=null, message=OuterBean#execute(), date=Mon Jul 18 09:00:27 CEST 2016}.
FINER: TX beginTransaction, status=STATUS_ACTIVE
FINEST: Connection acquired from connection pool [default].
FINEST: Execute query DataModifyQuery(name="SEQUENCE" sql="UPDATE SEQUENCE SET SEQ_COUNT = SEQ_COUNT + #PREALLOC_SIZE WHERE SEQ_NAME = #SEQ_NAME")
FINEST: reconnecting to external connection pool
FINE: UPDATE SEQUENCE SET SEQ_COUNT = SEQ_COUNT + ? WHERE SEQ_NAME = ?
bind => [2 parameters bound]
FINEST: Execute query ValueReadQuery(name="SEQUENCE" sql="SELECT SEQ_COUNT FROM SEQUENCE WHERE SEQ_NAME = #SEQ_NAME")
FINE: SELECT SEQ_COUNT FROM SEQUENCE WHERE SEQ_NAME = ?
bind => [1 parameter bound]
FINEST: local sequencing preallocation for SEQ_GEN: objects: 50 , first: 301, last: 350
FINEST: assign sequence to the object (301 -> LogEntry{id=null, message=OuterBean#execute(), date=Mon Jul 18 09:00:27 CEST 2016})
FINER: client acquired: 187184807
FINER: TX binding to tx mgr, status=STATUS_ACTIVE
FINER: acquire unit of work: 2098992041
FINEST: persist() operation called on: LogEntry{id=null, message=InnerBean#execute()0.3957184758563761, date=Mon Jul 18 09:00:28 CEST 2016}.
FINER: TX beginTransaction, status=STATUS_ACTIVE
FINEST: Connection acquired from connection pool [default].
FINEST: Execute query DataModifyQuery(name="SEQUENCE" sql="UPDATE SEQUENCE SET SEQ_COUNT = SEQ_COUNT + ? WHERE SEQ_NAME = ?")
FINEST: reconnecting to external connection pool
FINE: UPDATE SEQUENCE SET SEQ_COUNT = SEQ_COUNT + ? WHERE SEQ_NAME = ?
bind => [2 parameters bound]
응용 프로그램이나 엔터티에서 어떤 잠금을 수행합니까? 컨테이너가 실제로 새 트랜잭션을 시작했는지 또는 주석을 무시하고 메소드가 더 큰 트랜잭션 컨텍스트로 래핑되었는지 확인할 수 있습니까? 로깅을 켜서 최고 수준으로 진행하고 진행 상황을 확인하십시오. – Chris
안녕하세요, @ 크리스, 생성 된 가장 멋진 로그를 추가했습니다. 나는 모든 것을 이해할 수는 없지만 두 가지 거래가 시작될 것임을 알았습니다. 만약 InnerBean에'@TransactionAttribute (REQUIRES_NEW)'주석을 남겨두면 모든 것이 잘 동작한다는 것이 제 견해에 부합 할 것입니다. 잠금과 관련해서는 명시 적 잠금을 수행하지 않습니다. 위의 코드는 CDI 빈을 통해 실행될 것이고 아무 것도 잠그지 않는 코드는 더 이상 존재하지 않습니다. – Filou
시퀀스를위한 연결 풀을 구성해야하므로 JTA 트랜잭션 외부에서 시퀀스 테이블의 시퀀스 번호를 얻거나 할당 할 수 있습니다. http://www.eclipse.org/eclipselink/documentation/2.4/concepts/data_access006.htm#CHDEFJHH 및 http://stackoverflow.com/questions/19732551/how-to-configure-an-eclipselink-jta-sequence를 참조하십시오. 비 -JTA 데이터 소스를 지정하는 방법을 보여주는 -connection-pool – Chris