[7장] 트랜잭션과 동시성 제어

신은지·2021년 11월 14일
0

복수의 쿼리 통합

트랜잭션을 다룰 수 있는 테이블

트랜잭션이란?

  • 복수의 쿼리를 연속적으로 사용해 일관성 있는 형태의 한 단위
    : 갱신은 복수 쿼리가 연속적으로 수행되는 경우가 많다
    : 갱신 전의 데이터에 SELECT 사용할 때, 복수 쿼리를 일관된 형태의 덩러리로 다뤄야 한다

  • MySQL 구조
    (1) MyISAM형 : 트랜잭션 사용 불가능한 단순 구조
    (2) InnoDB형 : 트랜잭션 사용 가능

  • 트랜잭션의 ACID 특성

    • Atomicity (원자성)
      : 데이터의 변경을 수반하는 데이터 조작이 전부 성공할지, 또는 전부 실패할지를 보증하는 구조
      : 모든 절차를 성공하면 트랜잭션에서 'COMMIT'를 실행, 처리 확정 = 조작 영구 저장. 결과 손실 X
      : 도중에 오류 발생하면 'ROLLBACK' 실행. 오류 직전 상태로 돌아갈 수 있다.
    • Consistency (일관성)
      : DB오브젝트에 정합성 제약을 추가해 일련의 데이터 조작 전후에 상태 유지를 보증하는 것.
    • Isolation (고립성, 또는 격리성)
      : 일련의 데이터 조작을 복수 사용자가 동시에 실행했을 때, 각각의 처리가 모순 없이 실행되는 것
      : 데이터베이스 오브젝트 테이블에 잠금(Lock)과 블록(Block)을 사용하여 트랜잭션 처리
      : 모순 없음 - 복수의 트랜잭션이 순서대로 실행되는 경우과 같은 결과를 얻을 수 있는 상태 (직렬화 기능 Serializable)

      ANSI 격리 수준
      : 직렬화 기능으로부터 격리 수준을 완화해 자신이 아닌 다른 트랜잭션 영향을 허용
         (1) 커밋되지 않은 읽기
         (2) 커밋 된 읽기
         (3) 반복 읽기
         (4) 직렬화 가능
      : 격리 수준의 완화에 따라 다음과 같은 현상 발생
         (1) 더티 읽기 : 트랜잭션이 커밋되기 전 다른 트랜잭션에서 데이터를 읽는 것
         (2) 애매한 읽기 : 트랜잭션이 이전에 읽은 데이터를 닷시 읽을 때, 2회 이후의 결과가 1회때와 다른 현상
         (3) 팬텀 읽기 : 트랜잭션을 읽을 때 선택할 수 있는 데이터가 나타나거나 사라지는 현상

    • Durability (지속성)
      : 일련의 데이터 조작을 완료하고 완료 통지를 사용자가 받는 시점에서 그 조작이 영구적이 되어 그 결과를 읽지 않는 것
      : 시스템 장애를 견딜 수 있다는 뜻

다른 커넥션에서는 어떻게 보이는가

  • 트랜잭션이 커밋되기 전, 다른 커넥션에서 DDL, DML 결과가 보이는 경우
    • DDL에 따른 암묵적 커밋
      : 한 개의 커넥션에 CREATE TABLE이 성공하면, 다른 커넥션에서도 참조 가능
    • 오토커밋 설정
      : 트랜잭션의 개시가 명시적으로 지정되지 않았을 때, 2가지 모드로 트랜잭션 구별
      (1) 하나의 SQL문이 하나의 트랜잭션으로 구분
      (2) 사용자가 COMMIT또는 ROLLBACK을 실행하기까지가 하나의 트랜잭션

복수 커넥션에서 읽기와 쓰기

InnoDB형 MySQL은 MVCC를 사용한다.

  • 아래 두 특성을 기억하자!
    • 읽기 수행할 경우, 개인 중이라도 블록되지 않는다. (읽기와 읽기도 서로 블록 X)
    • 갱신과 개인은 나중에 온 트랜잭션이 잠금을 획득하려고 할 때 블록된다.
      일정 시간을 기다리며 그 사이에 잠금을 획득할 수 없는 경우에는 '잠금 타임아웃'이 된다.

트랜잭션 격리 수준에 따른 외관상 차이

  1. 반복 읽기 (RR)
    : 기본값
    : 최초 쿼리 실행한 시점에 커밋된 데이터를 읽어들인다.
    : 복수 회의 쿼리 실행 사이에 다른 트랜잭션이 커밋하더라도, 그 내용은 반영되지 않는다.

  2. 커밋된 읽기
    : 쿼리를 실행한 시점에서 커밋된 데이터를 읽어들인다.
    : 같은 쿼리 복수 실행할 때, 다른 트랜잭션에서 커밋할 경우 최신 쿼리 실행 개시 시점에서 커밋된 데이터를 읽는다.

  3. 갱신을 수행하는 트랜잭션 자신
    : 트랜잭션 격리 수준이나 COMMIT/ROLLBACK에 관계 없이 자신이 수행한 갱신을 즉시 확인 가능

  4. 커밋되지 않은 읽기가 사용되지 않는 이유
    : 읽기가 블록되는 경우가 없기 때문에, 커밋되지 않은 읽기가 필요하지 않다.


잠금 타임아웃과 교착 상태

잠금 타임아웃과 교착 상태 발생 이유

  • 잠금 타임아웃
    : 갱신과 갱신이 부딪치는 경우, 나중에 온 갱신은 잠금 대기 상태가 된다.
    : 이때, 잠금 해제를 기다리는 쪽은 잠금을 기다릴 때 어느 정도를 기다릴지 설정할 수 있다.
    : innodb_lock_wait_timeout 사용

    잠금 대기로 타임아웃 발생하는 경우, DBMS 롤백 단위 다른 경우 존재 가능
    : 해당 트랜잭션 전체를 롤백하는 경우 vs 쿼리만 롤백하는 경우
    : MySQL의 기본 롤백은 오류가 발생한 쿼리이며, 트랜잭션 전체를 롤백하고 싶다면
       - 타임아웃 오류 후 명시적으로 ROLLBACK 실행
       - innodb_rollbak_on_timeoutt 시스템 변수 설정

  • 교착 상태
    : 트랜잭션 A와 트랜잭션 B가 서로 다른 테이블의 잠금을 얻었을 때,
    잠금을 유지한 채 서로 잠금을 건 자원에 잠금이 필요한 처리를 실행해서 아무리 기다려도 상황이 바뀌지 않는 상태.
    : OS에서 본 그 친구

  • 교착상태 빈도를 낮추는 대책

    • DBMS 전반적인 대책
      : 트랜잭션 자주 커밋하기
      : 정해진 순서로 테이블(그리고 행)에 액세스하게 한다
      : 필요 없는 경우에는 읽기 잠금 획득의 사용을 피한다
      : 쿼리에 의한 잠금 범위를 좁히거나, 잠금 정도를 더 작은 것으로 한다
      : 한 테이블의 복수 행을 복수 연결에서 순서 변경없이 갱신하는 것을 피한다.
    • MySQL 대책
      : 테이블에 적절한 인덱스를 추가해 쿼리가 인덱스를 타게 한다.
      : 인덱스가 사용되지 않는 경우, 필요한 행의 잠금이 아닌 스캔한 행 전체에 잠금이 걸리게 한다.

교착상태의 확인
: 클라이언트에서 롤백된 트랜잭션의 오류, 서버에서 오류 로그나 명령으로 확인 가능
: 상한 횟수를 정한 재시도 등의 처리나 트랜잭션 재실행 등으로 트러블을 해결해야 한다

해서는 안되는 트랜잭션 처리

  1. 오토커밋
    : 쿼리 단위로 커밋하는 설정. MySQL의 연결 기본값
    : 애플리케이션 잠금 실행하는 경우 커밋 부하가 너무 높다!
    적절한 단위와 트랜잭션 격리 수준을 이용해 오토커밋을 피해야 한다

  2. 긴 트랜잭션
    : 데이터베이스 트랜잭션의 동시성이나 자원의 유횻성을 저하한다.
    : 잠금과 블록 사이에 교차가 발생하면 교착 상태가 되고, 긴 트랜잭션 중 하나가 롤백될 수 있다.
    (1) 교착상태 빈도를 낮추는 방안 사용
    (2) 대량 처리를 적당한 여러개의 트랜잭션으로 나눠서 실행한다.
    (3) 아무것도 하지 않는 트랜잭션을 유의한다
    (4) 트랜잭션 중 대화 처리를 넣는다 : 불명확한 처리를 포함하지 않도록한다.
    (5) 처리 능력 이상의 트랜잭션 수 : 최적의 트랜잭션 수를 부하 실험을 수행해 측정하여 조절한다.

profile
호그와트 장학생

0개의 댓글