>source

데이터베이스에서 데이터를 읽고 시스템 'X'로 보내는 스프링 애플리케이션이 있습니다. 작업 실행기를 사용하여 스레드를 스핀 업하므로 동시에 행에 대한 데이터베이스를 읽는 5 개의 스레드가 있습니다. 각 스레드에 대해 고유 한 레code가 선택되었는지 확인해야합니다. 이를 달성하기 위해 JdbcTemplate을 사용하고 "업데이트를 위해 선택"합니다.

code를 작성했지만 로그에서 동일한 행을 선택하는 2 개의 스레드를 볼 수 있습니다. 이 문제의 근본 원인을 파악할 수 없습니다. 누구에게 제안이 있습니까?

try {
    List<Map<String, Object>> rows= getJdbcTemplate().queryForList(
                        SELECT_FOR_UPDATE,
                        new Object[] {a,b,c,d});
    for (Map<String,Object> row : rows) {
        Header a= new Header();
        a.setMailID(((BigDecimal)row.get("mailID")).intValue());
        a.setVersion(((BigDecimal)row.get("version")).intValue());
        //some other parameters to get
        getJdbcTemplate().update(UPDATE_MSG_STATE_VERSION_N_ORIG_MSG_STAT,
                                 x,
                                 a.getVersion()+1,
                                 y),
                                 a.getMailID(),
                                 a.getVersion());
        headers.add(a);
    }
}
UPDATE_MSG_STATE_VERSION_N_ORIG_MSG_STAT= update MESSAGE set MSG_STAT_CD= ?, VERSION_NBR= ?, ORIG_MSG_STAT_CD=?, LAST_UPD_TS=SYSTIMESTAMP where MESSAGE.MAIL_ID= ? and VERSION_NBR= ?
String SELECT_FOR_UPDATE= "select m.MAIL_ID mailID, m.VERSION_NBR version, m.MSG_STAT_CD state,"
                + "from message m "
                + "and m.MSG_STAT_CD in ('Nerwerw')"
                + " and m.create_ts > (sysdate -?)"
                + " and mod(mail_id,?)= ?"
                + " and ROWNUM <= ?"
                + " order by mt.MSG_PRIORITY FOR UPDATE";

귀하의 code가 귀하의 아이디어를 보여주기 위해 잘못 작성되었습니다 : 따옴표와 괄호가 일치하지 않고 일부가 의미가 없습니다 (예 : UPDATE_MSG_STATE_VERSION_N_ORIG_MSG_STAT= ...) 개선하십시오

Adrian Shum2021-02-23 10:16:26

Spring JDBC와 함께 작동하도록 업데이트를 선택한 적이 있습니까?

Arya2021-02-23 20:06:50

네, 작동시킬 수있었습니다.

user6418872021-02-23 20:06:50
  • 답변 # 1

    동일한 호출의 모든 작업이 하나의 트랜잭션에서 처리되도록 태그와 태그로 클래스에 주석을 달아야합니다.

    동일한 트랜잭션에서 처리되지 않으면 각 SELECT_FOR_UPDATE 가 다른 트랜잭션에서 발생하므로 스레드 쿼리가 동기화되지 않고 select_for_update는 중요하지 않습니다.

  • 답변 # 2

    거래 제어를 올바르게 설정 했습니까?

    그렇지 않은 경우 트랜잭션은 업데이트 문 기간 동안 만 발생하며 자동으로 커밋됩니다 (구문에 따라 Oracle을 사용하고 있다고 생각합니다).

    즉, 해당 기록의 잠금을 획득했지만 즉시 공개됩니다.

  • 답변 # 3

    데이터베이스를 수정할 수있는 권한이 있습니까? 귀하의 질문을 올바르게 이해하면 최근에 비슷한 문제가 발생하여 다음과 같은 계획을 구현했습니다.

    "thread_number"또는 이와 유사한 것과 같은 새 열을 데이터베이스에 추가하십시오. 0과 같은 일부 기본값으로 설정하십시오. 각 스레드에 고유 식별자를 부여하십시오. 그런 다음 "thread_number"를 처리하는 스레드의 식별자로 업데이트하여 데이터베이스의 레code를 "클레임"합니다. 그러면 SQL에 "where thread_number= 0"을 포함하면 쿼리 할 때 다른 스레드가이를 찾지 못합니다.

    어느 정도 광범위하다는 것을 알고 있지만 도움이되기를 바랍니다.

  • 이전 javascript : 슬롯 어린이의 Vue 스왑 주문
  • 다음 macOS 앱용 SwiftUI Xcode 12의 도구 모음에있는 검색 막대