데이터 베이스

트랜잭션과 격리 수준

쭈녁 2023. 12. 29. 17:46

 

트랜잭션 특징

 

원자성(Atomicity)

  • 트랜잭션이 DB에 보두 반영되거나 모두 반영되지 않아야 한다.

일관성(Consistency)

  • 트랜잭션의 작업 처리 결과는 항상 일관성 있어야 한다.

독립성(Isolation)

  • 한 트랜잭션이 동시에 병행될 때, 다른 트랜잭션이 연산에 끼어들 수 없다.

지속성(Durability)

  • 트랜잭션이 성공적으로 처리되면 영구적으로 반영되어야 한다.

 

Commit 과 Rollback

 

Commit : 하나의 트랜잭션이 성공적으로 끝나 DB에 지속성을 만족시켰음을 알리는 연산

 

Rollback : 하나의 트랜잭션 처리 중 하나가 비정상이였을때 원자성이 깨져 원래 대로 돌린다.

 

DBMS의 구조

 

DB의 구조는 Query Processor(쿼리 처리기) 와 Storage System(저장 시스템) 으로 나뉜다.

Buffer는 Storage System에 속하는 모듈 중 하나로 디스크로의 입출력 횟수를 줄이기 위해

Buffer의 레코드를 통해 관리한다.

 

UNDO

    - 수정된 Page들이 Buffer 교체 알고리즘에 따라 디스크에 입출력,

    - Buffer는 transaction이 연산에 실패하여 Rollback 해야하는 상황에 이전 UNDO logging를 기반으로 원상 복구하게 되는데 이 복구를 UNDO라고 한다.

 

 

MySQL의 엔진 종류

MySQL의 스토리지 엔진

 

1) MyISAM

  • Table과 Index를 다른 파일로 관리
  • Read Only가 많은 서비스는 MyISAM엔진이 효율적

2) InnoDB

  • 트랜잭션 처리가 필요하고 대용량의 데이터를 다루기 위해서는 InnoDB가 효율적
  • InnoDB는 Tablespace 개념을 사용한다.
  • PK를 기준으로 클러스터링
  • 오라클 의 주요 개념이 많이 적용됨( MVCC , 테이블 스페이스 등)
    • ** MVCC: 읽기 작업시, 다른 트랜잭션의 락이 풀리기 기다리지 않고 읽기 가능

 

Database Lock

데이터베이스의 동시성을 보장하기 위하여 잠금 장치 역할한다. 하나의 데이터를 동시에 여러명이 조작할 수 없도록 함

 

락의 종류

 

1. 글로벌 락 - write의 락을 적용함. 모든 테이블의 락을 획득한다.

 

2. 테이블 락

 

    - Read Lock : 한쪽에서 데이터를 읽을 때 Read Lock을 획득하면 쓰기 불가능

    - Write Lock : 한쪽에서 데이터를 수정하거나 insert할 때 반대쪽에서 읽기 불가능

더보기

명시적 방법 : LOCK TABLES table_name [ READ | WRITE ]

묵시적 방법 : 쿼리 실행시 자동 잠금, 잠금해

 

3. 네임드 락(유저 레벨)

    -get_lock 명령어로 lock을 획득한다. 한쪽에서 획득하면 다른쪽에선 획득 불가능.

 

4. 메타데이터 락

    - 데이터베이스의 구성(스키마,테이블,뷰)의 이름이나 구조를 변경하는 경우 획득하는 잠

 

5. 레코드 락

    - select되는 Row에 락을 거는 기능(SQL이 자동으로 실행해줌)

 

6. Auto Increment Lock

    - ID와 같이 데이터 생성 시 자동으로 값이 할당되는 값의 경우 insert되는 잠시 동안 걸리는 Lock

 

격리수준 Isolation Level 

여러 트랜잭션이 동시에 처리될 때 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있게 허용할지 말지 결정함

 

격리 수준의 종류 (격리수준 오름차순)

  1. read uncommitted == dirty read
    • 거의 사용되지 않음
    • 트랜잭션의 변경 내용이 commit이나 rollback 여부에 상관 없이 보임
      • 에러가 발생해서 rollback된 항목을 commit 전에 접근해서 에러가 발생할 수 있음
  2. read committed
    • 트랜젝션이 완료된 데이터만 다른 트랜잭션에서 조회 가능
    • 커밋되기 전에는 언두로그에 있는 곳의 데이터를 읽어옴
      • 언두로그 → 뭔가 잘못되면 돌려야돼서 임시로 저장하는 공간
    • unrepeatable read(반복 읽기 불가) : 상황 가정 한 트랜잭션 내에서 타 트랜잭션이 테이블을 조작하면 조회 결과물이 다르게 나올 수 있다(일관성에 어긋남) 
      • 커밋 전에 불러오면 가져오는 값이 없고,
      • 커밋 후에 불러오면 가져오는 값이 있음
      • 문제 없어 보이지만 정합성에 어긋남
  3. repeatable read
    • 언두 영역에 백업된 이전 데이터를 이용해서 동일 트랜잭션에서는 같은 내용을 보여줄 수 있도록 함
    • phantom read
      • 언두 레코드에는 lock을 걸 수 없어서 같은 트랜잭션에서 조회 가능
      • 언두로그에 존재하지 않던 새로운 컬럼이 나옴 이를 phantom read (유령)라 함

상황 예시)

더보기

상황 설정 사용자 A와 사용자 B가 각각 다른 트랜잭션을 수행하고 있음. 사용자 A는 특정 조건 (예: 잔액이 5,000원 이상인 계좌) 을 만족하는 모든 계좌의 수를 확인하려고 함.
  1. 사용자 A의 첫 번째 쿼리 사용자 A는 트랜잭션에서 조건을 만족하는 계좌가 총 10개임을 확인함.
  2. 사용자 B의 데이터 변경 동시에, 사용자 B는 다른 트랜잭션에서 새로운 계좌를 추가함. 이 계좌는 사용자 A가 사용한 같은 조건을 만족함. 사용자 B의 트랜잭션이 커밋되어 새 계좌가 데이터베이스에 추가됨.
  3. 사용자 A의 두 번째 쿼리 사용자 A는 같은 트랜잭션에서 다시 조건을 만족하는 계좌의 수를 확인함. 이번에는 총 11개의 계좌가 있음을 확인함.

4. serializable

  • 동시성이 중요한 데이터베이스의 경우 거의 사용되지 않음
  • read도 lock을 획득해야만 가능함
    • read가 lock을 가지고 있기 때문에, write나 update, delete등을 실행할 수 없음