"동시성 제어와 회복" 그리고 트랜잭션

김지윤·2023년 6월 7일
0

데이터 베이스

목록 보기
4/7

<데이터 베이스에서 중요한 2가지!>

- 동시성 제어 :

트랜잭션 단위로 처리되어야 하는 프로세스에서 타인과 동시에 접근할 수 없게 하는 처리

- 회복 :

한 프로세스에 여러 SQL문이 있을 경우, 중간에 끊겨 데이터 손실이 일어나면 안되기 때문에, 꼭 트랜잭션 단위로 묶어준다.




트랜잭션이란?

예를 들어 티켓팅을 할 때, 티켓팅 SQL문 묶음이 "한번에 처리" 되어야, 다른 사람의 요청과 혼돈되지 않는다.
이렇게 한번에 처리해 주어야 하는 문장들 묶음을 "트랜잭션"이라고 한다.




트랜잭션이 갖추어야할 성질 (ACID 성질)

  • Atomicity 원자성 : 원자적 단위로 전부 실행되던지, 아예 실행되지 않던지 해야한다. 회복을 통해 보장한다.

  • Consistency Preservation 일관성 : 데이터베이스는 일관성 있게 유지할 수 있도록 해야한다. 동시성 제어와 회복을 통해서 보장한다.

  • Isolation 고립성 : 하나의 트랜잭션은 다른 트랜잭션들과 분리되어야 한다. 동시성 제어를 통해 보장한다.

  • Durability 지속성 : 트랜잭션 완료 후에는 그 기록이 사라지면 안된다. 회복을 통해 보장한다.





<고립성에는 등급이 있다.>

  • 너무 많은 설정은 기능에 영향을 미치기 때문에 4가지 옵션 중 하나를 선택하여 설정한다.

1. Read Uncommitted (레벨0) : 트랜잭션끼리 접근이 이루어지는 가장 무방비한 상태, 사용하지 말아야함

2. Read committed (레벨1) : 잘못 읽는 것은 방지하지만, 비반복적 읽기와 phantom record 문제는 여전하다.

3. Repeatable Read (레벨2) : 트랜잭션 종료까지 데이터의 변경 방지를 보장한다. phantom record 문제는 여전하다.
commit전에는 항상 같은 값을 읽게함.

4. Serializable (레벨3) : 동시성 문제를 모두 보장해주지만 성능이 떨어진다.





하지만 요즘 사용하는 maria DB에서는 좀 다르다!

접근을 못하는 동안엔 lock 대기를 하고 있다.




동시성 제어를 '안하면' 생기는 문제점


1. lost update


마지막에 rollback을 해버려 타인이 작업한 내용을 잃어버림
ex. 표 2중 판매



2. dirty read


마지막에 rollback을 해버려 타인이 데이터를 잘못 읽어갔다.
ex. 잘못된 정보 제공



3. 부정확한 요약/합산

T3에서 모든 값을 합산하고 있는데, 타인이 값을 중간에 바꿔버림



4. unrepeatable read

같은 데이터를 두번 읽었을 때, 둘다 정확한 정보이긴 했지만, 둘의 내용이 달랐던 것



5. phantom record

상대가 데이터를 변경하는 도중에 나에게 그 데이터가 보였다, 안보였다 하는 현상





동시성 제어 하는법!

로크 기법을 이용해 자신이 사용하는 동안은 다른 사람이 접근하지 못하도록 한다.

이진 로크 (Binary Lock)

  • locked : 로크가 걸린 상태

  • unlocked : 로크가 해제된 상태

  • Lock_item(x) : x 잠그기 수행

  • Unlock_item(x) : x 풀기 수행

  • 데이터를 읽거나 쓰기를 수행하기 전에, 먼저 잠궈야 한다.

  • 사용을 마친 후에는 자물쇠를 풀어준다. (트랜잭션 완료 시점에 해줘야 한다)



로크 종류

  • 공유 로크(shared_lock) :
    • 읽기만 하고 싶을 때 사용할 수 있다.
    • 내가 읽을 때, 다른 사람도 읽을 수 있다.
    • 내가 읽을 때, 다른 사람은 write를 할 수 없다.

  • 배타적 로크(exclusive_lock) :
    • write하고 싶을 때, 사용할 수 있다.
    • 다른 사람이 읽고, 쓰는 것을 모두 막아준다.

  • 호환성 테이블



로크는 "두 단계 로킹 (Two-Phase Locking, 2PL)"으로 사용한다.

트랜잭션을 시작하기 전, 데이터에 접근할 모든 것들에 대해 lock 요청을 받는다. 이 과정이 "확장단계"이고, 이 단계에서 쌓인 lock들을 하나씩 unlock 해주며 데이터에 접근할 수 있도록 하는 과정이 "수축단계"이다.



교착 상태 (locking의 단점)

자원에 동시에 접근이 이루어져 어떠한 작업도 시작할 수 없는 상태



기아현상

자원의 할당이 적절히 이루어지지 않아서 무한 대기만 하는 프로세스가 존재할 수 있는 것



자원의 단위 조절하기 "다중 단위 크기 로킹"

  • Lock을 단위 크기가 작은 것부터 선택할수 있게 함으로서 더 많은 트랜잭션들이 접근할 수 있다.

  • 동시성이 높다.

  • 보통 '다중 단위 크기 로킹'이 Default로 설정되어 있다.






회복이 필요한 이유

  • 트랜잭션 고장 : 프로그램 안에서 오류가 나는 경우

  • 시스템 고장 : 컴퓨터 시스템이 고장난 경우

  • 매체 고장 : 하드디스크가 고장난 경우



해결법

  1. 프로세스에서 데이터를 쓸 때, 현대의 컴퓨터는 속도를 빠르게 하기 위해, Disk에 일일이 저장하지 않고 buffer(주기억장치)에만 기록하도록 한다.
    그런데 컴퓨터가 고장이 나면 데이터가 다 사라지게 된다. 이를 해결하기 위해 "어떠한 작업을 했었는지" 로그 기록을 남겨 회복할 수 있도록 한다. -> commit

  2. 트랜잭션 단위로 실행 중, 중간에 문제가 생겼을 때, 원래대로 rollback 해주어야 한다. 로그 기록을 보고 돌아갈 수 있다. -> rollback

  • 로그 기록만 디스크에 남겨 용량이 작다.



로그 : 일련의 과정을 모두 기록하는 것

redo : 로그 파일을 재실행

undo : 완료되지 못한 트랜잭션 취소



로그 우선 출력 기법

정보가 갱신되면 우선 "로그"에 먼저 기록하고, 데이터 베이스에 저장한다.



즉시 갱신

  • log에 기록하는 동시에 DBMS에 저장
  • 회복할 때, 종료된 트랜잭션은 REDO 실행
  • 회복할 때, 진행 중인 트랜잭션은 LOG 폐기



지연 갱신

  • commit을 해야 DBMS에 저장
  • 회복할 때, 종료된 트랜잭션은 REDO 실행
  • 회복할 때, 진행 중인 트랜잭션은 log기록을 보고 UNDO 실행



검사점

buffer에만 있는 기록들을 주기적으로 DBMS에 저장해 주는 것

profile
꾸준하게 공부하고 기록하는 개발자

0개의 댓글