반응형
Greensky0026
삽질러의 대환장 공사판
Greensky0026
전체 방문자
오늘
어제
  • 분류 전체보기 (241)
    • Language (56)
      • JAVA (13)
      • Swift (38)
      • Kotlin (4)
      • Dart (0)
      • PHP (0)
      • JavaScript (1)
    • IDE & Framework (92)
      • Spring (10)
      • Android (48)
      • iOS (8)
      • NodeJS (1)
      • CodeIgniter (3)
      • Flutter (1)
      • 분류중 (18)
    • Infra (8)
    • Database (12)
    • VCS (4)
    • Debug Log (34)
      • java (7)
      • swift (3)
      • Android (9)
      • Web (7)
      • 삽질기 (7)
    • Others (19)
      • 코딩테스트 풀이 (0)
      • IT 이야기 (18)
    • 쉼터 (2)
    • 개발공부 (14)
      • Network (1)
      • 자료구조와 알고리즘 (2)
      • Code design (8)
      • ETC (1)
      • 아카이브 (1)

블로그 메뉴

    공지사항

    • 프로그래머스 코딩 테스트 관련글 비공개 처리

    인기 글

    태그

    • ios
    • 개발
    • reduce
    • 프로그래머스
    • kotlin
    • JSP
    • 예제
    • level1
    • Java
    • 공부
    • 타입
    • 프로그래밍
    • Android
    • map
    • swfit
    • swift
    • 구축
    • xcode
    • 코딩테스트
    • IT

    최근 댓글

    최근 글

    티스토리

    hELLO · Designed By 정상우.
    Greensky0026

    삽질러의 대환장 공사판

    [MySQL-MyBatis] insert후 pk를 반환하는 selectKey와 useGeneratedKey의 동시성 이슈
    Database

    [MySQL-MyBatis] insert후 pk를 반환하는 selectKey와 useGeneratedKey의 동시성 이슈

    2023. 5. 19. 17:18
    반응형

    0. 개요

    MyBatis를 쓰면서 INSERT된 행의 PK를 획득해야할 일이 자주 있습니다.

    이럴때 사용하는 방법이 두 종류인데요, selectKey구문과 insert 구문의 속성인 useGeneratedKeys입니다.

    이중 하나가 동시성 이슈가 있다는 말을 들어서 찾아보게 되었습니다.

    1. SelectKey

    <insert id="..." parameterClass="..." >
    
    	INSERT INTO...
    
        <selectKey resultType="long" order="AFTER" keyProperty="tid">
            SELECT LAST_INSERT_ID()
        </selectKey>
    </insert

    보통 INSERT 쿼리문 내부에 selectKey블럭을 입력해서 사용합니다.

    속성값들은 아래와 같은 의미를 가지고 있습니다.

    • result type : 반환할 pk의 타입
    • order : SELECT LAST_INSERT_ID()를 언제 실행할지 결정(감싼 쿼리문의 전, 후)
    • keyProperty : 반환받을 PK가 매핑될 속성을 지정 (ex - PK칼럼이 tid여도, id로 받을수 있음)

    반환받은 PK는 쿼리를 수행할 때 parameter로 사용한 객체에 매핑됩니다.

    keyProperty속성을 명시했다면  해당 속성에 매칭되며, keyProperty속성을 명시하지 않았다면 테이블 PK속성명으로 매핑됩니다.

    • parameter가 Map인 경우, key(PK 속성명)-value 쌍으로 저장
    • 커스텀 객체를 사용할 경우 해당 객체의 속성에 매핑되며, 프로퍼티가 없다면 매핑x

    2. useGeneratedKeys 

    <insert id="insertQna" useGeneratedKeys="true" keyProperty="seq">
    	//...
    </insert>

    insert 구문의 속성에 입력해 사용합니다.

    LAST_INSERT_ID()와 같은 쿼리를 직접 실행하지 않고, 데이터베이스가 자동으로 생성한 키 값을 반환하도록 합니다.

     

    반환받은 PK는 쿼리를 수행할 때 parameter로 사용한 객체에 매핑됩니다.

    keyProperty속성을 명시했다면  해당 속성에 매칭되며, keyProperty속성을 명시하지 않았다면 테이블 PK속성명으로 매핑됩니다.

    • parameter가 Map인 경우, key(PK 속성명)-value 쌍으로 저장
    • 커스텀 객체를 사용할 경우 테이블의 PK와 동일한 프로퍼티에 매핑되며, 동일한 프로퍼티가 없다면 매핑x

    3. 동시성 이슈

    두 구문은 자동으로 생성된 키 값을 가져와서 매핑하는 것으로 목적은 같습니다.

    하지만 실행 방법은 상이합니다.

    그렇다면 어느쪽이 동시성 이슈가 생길 수 있을까요? 바로 selectKey입니다. 

    selectKey는 SELECT LAST_INSERT_ID()의 결과를 반환하기 때문에, 싱글서버 싱글스레드에서 사용하면 안전하겠지만,
    멀티 인스턴스, 멀티 어플리케이션 서버에서는 안전하지가 않습니다.

     

    SELECT 쿼리를 수행해 PK를 반환하기 떄문에 위 사진처럼 다른 쿼리와 충돌이 발생할 수 있습니다.

    반면,  useGeneratedKeys 속성은 데이터베이스가 자동으로 생성한 키 값을 반환하도록 하기 때문에,

    INSERT 쿼리 실행 후 바로 키 값을 받아올 수 있습니다.

    따라서, useGeneratedKeys 속성을 사용하는 것이 selectKey 구문보다 동시성 이슈가 적고, 더 안전하게  키 값을 가져올 수 있습니다.

    반응형
    저작자표시 비영리 (새창열림)

    'Database' 카테고리의 다른 글

    MySQL] 조인(Table join) 종류  (0) 2023.01.25
    Mybatis) 조건문 if-else -> choose-when-otherwise  (0) 2022.08.21
    [MySQL] ON DUPLICATE KEY UPDATE [짧]  (0) 2022.05.23
    [MySQL] 복합키 설정하기 [짧]  (0) 2022.05.23
    Procedure 기본  (0) 2022.05.03
      'Database' 카테고리의 다른 글
      • MySQL] 조인(Table join) 종류
      • Mybatis) 조건문 if-else -> choose-when-otherwise
      • [MySQL] ON DUPLICATE KEY UPDATE [짧]
      • [MySQL] 복합키 설정하기 [짧]
      Greensky0026
      Greensky0026
      점이 모여 선이 된다. 내 삽질도 언젠간 거대한 지하 도시가 되겠지!

      티스토리툴바