DB(Hibernate 및 Oracle 10g)에서 동일한 행을 읽는 두 개의 서로 다른 스레드를 방지하는 방법
두 개의 서로 다른 스레드 T1과 T2가 동일한 데이터베이스에 동시에 액세스하고 동일한 테이블에서 데이터를 가져온다고 가정해 보겠습니다.
이제 스레드 시작 시 테이블에서 데이터를 가져와 행을 컬렉션에 저장해야 합니다. 그러면 다른 곳에서 작업을 수행하는 데 사용할 수 있습니다.두 스레드가 동일한 데이터를 처리할 수 없기를 원하는데, 이는 중복된(그리고 긴) 작업을 초래하기 때문입니다.좀 더 구체적으로 말하자면, 이것은 시작할 때 일부 레코드를 로드하고 추가 작업을 위해 모음에 저장해야 하는 엔터프라이즈 애플리케이션입니다.문제는 클러스터 환경에서 이로 인해 서로 다른 두 인스턴스가 동일한 데이터를 로드하여 작업이 중복될 수 있다는 것입니다.따라서 행을 단일 인스턴스에 의해 한 번만 로드하기를 원합니다.
어떻게 하면 그 시나리오를 피할 수 있을까요?
저는 현재 Hibernate와 Oracle 10g를 사용하고 있습니다.지금까지 제 솔루션은 다음과 같습니다.
행을 프로그래밍 방식으로 잠급니다.이를 읽는 첫 번째 스레드는 일부 "잠긴" 열을 true로 설정하지만, 행을 "처리됨"으로 설정하지 않고 첫 번째 스레드가 죽으면 교착 상태가 발생할 가능성이 매우 높습니다.
비관적 잠금 사용.LockMode로 해봤습니다.업그레이드하지만 두 스레드의 데이터를 동시에 읽을 수 있기 때문에 도움이 되지 않는 것 같습니다.
public List<MyObject> getAllNtfFromDb() { Session session = HibernateUtil.getOraclesessionfactory().openSession(); Query q = session.createQuery( "from MyObject n where n.state = 'NEW'"); List<MyObject> list = (List<MyObject>) q.list(); for (int i=0; i<list.size(); i++) session.lock(list.get(i), LockMode.UPGRADE); return list; }
다른 힌트는?내가 뭘 잘못하고 있는 거지?
감사해요.
사용해야 합니다.PESSIMISTIC_WRITE
쿼리 시:
Query q = session
.createQuery("from MyObject n where n.state = 'NEW'")
.setLockOptions(new LockOptions(LockMode.PESSIMISTIC_WRITE));
List<MyObject> list = (List<MyObject>) q.list();
상위 개체를 잠그면 충분합니다.교착 상태가 반드시 발생하는 것은 아닙니다.시간 초과 대기 중인 다른 스레드보다 먼저 잠금을 해제하지 않으면 잠금 획득에 실패할 수 있습니다.
Oracle을 사용하고 있으므로 SELECT FOR UPDATE는 다음과 같이 작동합니다.
UPDATE의 경우 ...을 선택하면 해당 행에 대한 UPDATE 문을 실행한 경우와 마찬가지로 해당 행과 관련 인덱스 항목이 잠깁니다.다른 트랜잭션은 해당 행을 업데이트하거나, SELECT ... LOCK IN SHARE MODE를 수행하거나, 특정 트랜잭션 격리 수준에서 데이터를 읽는 것을 차단합니다.일관된 읽기는 읽기 보기에 있는 레코드에 설정된 잠금을 무시합니다. (이전 버전의 레코드는 잠글 수 없습니다. 레코드의 메모리 내 복사본에 실행 취소 로그를 적용하여 재구성됩니다.)
따라서 T1이 일부 행에 대한 배타적 잠금을 획득한 경우 T2는 T1이 커밋하거나 롤백할 때까지 해당 레코드를 읽을 수 없습니다.T2가 READ를 사용한 경우_UNCommitted 분리 레벨을 사용하면 T2는 실행 취소 로그를 사용하여 쿼리가 시작될 때처럼 데이터를 재구성하므로 잠금 레코드를 차단하지 않습니다.SQL 표준과 대조적으로 Oracle READ_커밋되지 않은 의지:
일관된 답변을 제공하거나 수정하기 위해 Oracle Database는 쿼리가 시작될 때 이 행이 포함된 블록의 복사본을 만듭니다.Oracle Database는 수정된 데이터를 우회하여 데이터를 읽고 실행 취소(롤백) 세그먼트에서 재구성합니다.트랜잭션이 커밋될 때까지 기다리지 않고 일관성 있고 정확한 답변이 반환됩니다.
언급URL : https://stackoverflow.com/questions/27968877/how-to-avoid-two-different-threads-read-the-same-rows-from-db-hibernate-and-ora
'source' 카테고리의 다른 글
YAML 파일을 Python 객체로 구문 분석/읽기하는 방법은 무엇입니까? (0) | 2023.08.05 |
---|---|
null 가능한 열을 사용하여 MySQL 테이블을 조인하는 방법은 무엇입니까? (0) | 2023.08.05 |
내가 내 스프링 API에 게시하려고 할 때 403 금지? (0) | 2023.08.05 |
모델을 동기화하면 UNSIGNED BIGINT가 UNNSIGNED BIGINT로 수정됩니다(19). (0) | 2023.08.05 |
로컬 호스트에서 MariaDB(MySQL) 인스턴스에 연결하려면 어떻게 해야 합니까? (0) | 2023.08.05 |