OLTP기술 (트랜잭션,LOCK)

K·2022년 6월 16일
0

SQL BOOSTER

목록 보기
8/12

1. 트랜잭션

  • 반드시 한번에 처리되어야 하는 논리적 작업단위 (EX. 은행 계좌 이체 처리등)
  • COMMIT은 트랜잭션중 변경된 데이터를 모두반영하고 종료
  • ROLLBACK은 트랜잭션중 진행된 작업을 모두 취소하고 종료.
  • SQL문장에서 에러가나도 에러발생한 문장만 ROLLBACK시킬뿐 트랜잭션을 여전히 살아있음.
    명시적으로 ROLLBACK을 실행해야만 트랜잭션 전체를 되돌릴 수 있다.
  • 트랜잭션은 데이터 변경 SQL이 실행되는 순간 시작, 시작된 트랜잭션은 COMMIT이나 ROLLBACK을 만나기 전까지 유지
  • 요점
    • 트랜잭션은 한번에 이루어져야하는 작업단위
    • COMMIT이나 ROLLBACK으로 종료가 이루어진다.
    • COMMIT종료시 트랜잭션 변경사항은 모두 DB에 실제반영
    • ROLLBACK종료시 트랜잭션 시작 이전으로 복구
    • 트랜잭션 내에서 에러가 발생했다고해서 자동 ROLLBACK이 수행되진않는다.

2. 트랜잭션 고립화 수준

  • 하나의 트랜잭션에서 작업중인 데이터가 다른 트랜잭션에 영향을 받지 않는 정도.
  • 하나의 트랜잭션에서 작업중인 데이터를 다른트랜잭션에서 어느정도까지 접근가능한 정도
  • 고립화수준이 낮으면 서로 다른 트랜잭션간 접근이가능
    고립화 수준이 높으면 조회만 한 데이터도 다른 트랜잭션이 변경 못함
  • 고립화 수준 : READ UNCOMMITTED - READ COMMITED - REPEATABLE READ - SERIALIZABLE READ
  • 오라클의 기본 고립수준은 READ COMMITTED

2.1 READ COMMITTED : UPDATE -SELECT 테스트

  • 세션1 변경 후 COMMIT안함 > 세션2 조회시 변경전데이터조회
  • 세션1 변경 후 COMMIT안함 > 세션2 동일데이터 변경 불가. 대기상태(WAIT)

2.2 READ COMMITTED : INSERT-INSERT테스트

  • 세션1 ACC4 INSERT COMMIT안함 > 세션2 ACC4 INSERT COMMIT안함 > 세션2 WAIT
    > 세션1 COMMIT > 세션2 오류 PK필드에 동일한 ACC4입력으로인한 오류
  • 세션1 ACC5 INSERT > 세션2 ACC99 INSERT (NO WAIT) > 세션2 ACC5 INSERT (WAIT)
    > 세션1 COMMIT > 세션 2 중복에러 > 세션2 ROLLBACK < 세션2 ACC99 INSERT까지 취소

2.3 READ-COMMITTED특징

  • 한 트랜잭션 변경중데이터는, 다른트랜잭션에서 변경전 데이터만 조회가능
  • 한트랜잭션이 변경중 데이터는 다른 트랜잭션에서 동시변경 불가 (WAIT상태됨)
  • 동일 PK, UNIQUE KEY 데이터가 동시입력되면 후행트랜잭션은 대기상태
  • 에러가발생해도 트랜잭션 전체 ROLLBACK안됨.

3. 락(LOCK)

  • 데이터에 잠금을 걸어놓는장치, 데이터를 잠근 세션 외에 다른세션들은 잠긴데이터에 접근불가.
  • 잠금을 통해 고립회 수준을 구현할 수 있다.
  • 데이터 변경하면 해당 ROW에 락을 걸고 트랜잭션이 COMMIT또는 ROLLBACK할때까지 유지
  • 2.1 2.2 2.3의 테스트에서 WAIT가 발생하는것이 선행 트랜잭션에서 LOCK을걸었기 때문

3.1 SELECT ~ FOR UPDATE

  • SELECT는 수행중인 트랜잭션 이전 데이터를 가져오므로 값의 차이가발생
  • SELECT ~ FOR UPDATE사용지 동시접근하는 데이터의 트랜잭션이 완료될때까지 WAIT하므로
    동시발생 트랜잭션에 의한 값 오류방지가능.
  • NOWAIT 옵션 : 대기상태에 빠지자 마자 예외 발생
  • WAIT SECONDS옵션 : 대기할 초를 설정, 해당시간초과시 예외 발생
  • 예외 발생시 트랜잭션을 ROLLBACK처리하고 나오거나 재처리 유도가능, 업무에 맞게 사용
  • 꼭 종료(COMMIT, ROLLBACK)해줘야함

3.2 대기(WAIT) 상태

  • 대기상태 세션이 많아지면 시스템이 장애로 빠질수 있음.
  • 대부분 시스템은 DB연결 및 접근에 폴링(Polling)처리.
  • 폴링은 WAS에서 특정 수만큼 세션을 DB와 미리 연결해놓고 여러명의 사용자가 세션을 공유해 사용하는 방식
  • DB와 연결을 맺는 작업은 WAS와 DB모두 많은 자원을 소모하므로 폴링방식 사용이 일반적
  • 폴링을 사용하는 구조에서 연결된 세션이 모두 대기상태에 빠지면 시스템은 더는 작동하지 않음
  • 세션이 대기상태에 빠지는것은 느린SQL과 종료(COMMIT OR ROLLBACK)되지 않은 락에 의해서
  • 느린 SQL이많을수록 세션을 사용하기위한 대기시간이 길다.
  • 느린것보다 더무서운것은 제대로 종료되지않은 트랜잭션, 락으로 인해 세션이 무한정대기상태에 빠질 수 있음.
  • 시스템 동시성 높이려면 불필요한 SELECT~FOR UPDATE피하고 트랜잭션은 항상 제대로 종료

3.4 데드락(DEAD-LOCK,교착상태)

  • 시스템 개발 후 가장 잡아내기 어려운 에러중하나가 데드락
  • 첫 세션이 두번째 세션의 작업이 끝나기를 기다리고있고, 두번째 세션도ㅗ 첫번째 세션의 작업이 끝나기를 기다리는상태 (상호대기)
  • 락은 데이터정확성을 위해 기다리는(정상적인) 상태지만, 데드락은 더는 트랜잭션을 진행할 수 없는 상태.
  • 세션1에서 ACC1을 SELECT FOR UPDATE, 세션2에서 ACC2를 SELECT FOR UPDATE
    > 트랜잭션 종료전에 세션1에서 ACC2를 UPDATE시도, 세션2에서 ACC2을 UPDATE시도
    > DEAD LOCK
  • 바로위 예제상황을 막기 위해서는 ACC1과 ACC2에 동시에 락을 생성하면된다.
    아래처럼 하면 세션1에서 처리하는동안 세션2는 대기가 되고 세션1종료후 세션2수행됨.

    SELECT T1.ACC_NO, T1.BAL_AMT FROM M_ACC T1
    WHERE T1.ACC_NO IN ('ACC1','ACC2') FOR UPDATE;

3.5 트랜잭션 최소화

  • 대기세션이 많을수록 시스템은 느려지므로 데이터 변경이 포함된 트랜잭션은 최적화가 필요
  • SQL단위로 최적화가 필요하며, 유사반복실행되는 SQL을 합쳐서 트랜잭션길이 최소화해야한다.
  • 줄이기위해 SQL복잡도가 올라가는것은 유지보수관점에서좋지않다
  • 다른개발자가 알아볼수있는선에서 복잡하지 않게 SQL을 구현해야 한다.

3.6 방어로직

  • SELECT ~ FOR UPDATE 사용시 조회시점부터 락을 생성해 동시성을 떨어트리는 단점이있음
  • 방어로직을 사용하면 동시성을 떨어트리지 않고, 데이터 정확성 확보가능
  • 조회 시점에 잔액을 저장해놓고, 변경시점에 잔액이 변경되지 않았을때만 UPDATE
  • 테이블에 최종변경일시와 같은 변경 기록 컬럼을 추가해 사용할 수 있음.
    조회시점과 변경시점에 최종변경일시 값이 다르다면, 누군가 중간에 데이터를 변경한것이므로
    예외 처리하면 된다.
  • 데이터 조회시점에는 변경락을 발생시키지 않는것이 핵심.

3.7 불필요한 트랜잭션의 분리

  • 트랜잭션의 주요 연관성이 떨어지는 작업을 분리하면 트랜잭션 실행시간을 줄일 수 있음.
  • 이로인한 트랜잭션에서 만든 락을 빠르게 해소할 수 있으며 데이터베이스 동시성을 높일수있음
  • EX) 주문처리 트랜잭션에서 주문관련 처리는 모두 완료되었으나, 문자발송 로직이 문제가 생겨 락이발생하는 경우
profile
늙어가면서 기억을 남기는 개발자

0개의 댓글