Search
Duplicate
📒

[Database Study] 03-5. 동시성제어, DB 락

상태
수정중
수업
Database Study
주제
Transaction
연관 노트
3 more properties
참고

동시성 제어(Currency Control)

NOTE
하나의 자원을 두고 여러 개의 연산들이 경합하는 경우 데이터의 정합성을 깨트린다!
2개 이상의 트랜잭션이 같은 데이터를 사용하는 경우
트랜잭션의 고립성은 상호간의 트랜잭션을 독립적으로 만들어 주었다.
그러면 2개 이상의 트랜잭션이 하나의 값에 접근하는 경우에는 어떻게 되는가?
2개의 트랜잭션이 모두 읽기작업 ⇒ 문제없음
1개의 트랜잭션 쓰기, 1개의 트랜잭셕 읽기 ⇒ 문제발생!
2개의 트랜잭션 쓰기 ⇒ 문제 발생!

갱신손실(Lost Update)

NOTE
하나의 값에 계속해서 덮어쓰기(Overwrite)하여 데이터의 갱신이 무효화 되는 현상!
하나의 트랜잭션이 갱신한 내용을 다른 트랜잭션이 덮어써서 갱신이 무효화됨
2개의 트랜잭션이 1개의 데이터를 동시에 갱신할 때 발생
데이터베이스에서 절대 발생하면 안되는 현상

모순성(Inconsistency)

NOTE
어떤 값은 갱신 전의 값을, 다른 값은 갱신 후의 값을 읽어 데이터가 불일치 하는 것!
T1 읽기전 x,y (1500, 1000) → x는 갱신되기전 값을 가져옴 T1 읽기후 x,y (5400, 3000) → y가 갱신된 값을 가져옴
다른 트랜잭션들이 해당 항목 값을 갱신하는 동안 한 트랜잭션이 두 개의 항목 값 중 어떤 것은 갱신되기 전의 값을 읽고 다른 것은 갱신된 후의 값을 읽게 되어 데이터의 불일치가 발생

연쇄 복귀(Inconsistency)

NOTE
두 트랜잭션이 동일한 데이터 내용을 접근할 때 발생!
두 트랜잭션이 동일한 데이터 내용을 접근할 때 발생!
한 트래잭션이 데이터를 갱신한 다음 실패하여 Rollback 연산을 수행하는 과정에서 갱신과 Rollback 연산을 실행하고 있는 사이에 해당 데이터를 읽어서 사용할 때 발생하는 문제

트랜잭션 스케줄

NOTE
트랙잭션 스케줄이란 그 연산들의 실행 순서를 의미한다!
3가지 방식이 존재
직렬 가능 스케줄
하나의 트랜잭션이 실행되면 해당 트랜잭션이 완료되어야 다른 트랜잭션이 실행됨
비직렬 가능 스케줄
트랜잭션의 직렬 수행 순서와 상관없이 병행 수행하는 방식
직렬 가능 스케쥴
서로 영향을 주지 않는 스케줄을 비직렬적으로 수행

락(Lock)

NOTE
여러 개의 트랜잭션들이 하나의 데이터로 동시에 접근하려고 할 때 이를 제어해주는 도구!
트랜잭션 T가 데이터 항목 X에 대해 Read/Write 연산을 수행하려면 lock을 해줘야함
트랜잭션 T가 실행한 lock에 대해서는 해당 트랜잭션이 종료되기전에 unlock을 해줘야함
트랜잭션 T는 다른 트랜잭션에 의해 이미 lock이 걸려있는 X에 대해 lock을 수행하지 못한다.
읽기 락(공유 락), 쓰기 락(베타 락)으로 구분된다.
# 읽기 락 SELECT ... FOR SHARE # 쓰기 락 SELECT ... FOR UPDATE or UPDATE, DELETE 쿼리
SQL
복사
실제 Lock을 얻는방법

공유락(s-lock)과 베타락(x-lock)을 사용하는 규칙

NOTE
데이터에 락이 걸려있지 않으면 트랜잭션은 데이터에 락을 걸 수 있다.
트랜잭션이 데이터 X를 읽기만 하는 경우 ⇒ 공유 락
트랜잭션이 데이터 X를 읽기/쓰기 하는 경우 ⇒ 베타 락
다른 트랜잭션이 데이터에 공유 락을 걸여둔 경우
공유 락의 요청은 허용
베타 락의 요청은 거부
다른 트랙잭션에 데이터에 베타 락을 걸어둔 경우
공유 락, 베타 락 둘다 허용받지 못한다.
트랜잭션이 락을 허용받지 못하면 대기 상태가 된다.

데드락

NOTE
2개 이상의 트랜잭션이 각각 자신의 데이터에 대하여 락을 획득하고 상대방 데이터에 대하여 락을 요청하면 무한 대기 상태에 빠질 수 있는 현상
트랜잭션 1은 bookid1을 락한다음 bookid2의 락을 요청 트랜잭션 2는 bookid2를 락한다음 bookid1의 락을 요청

트랜잭션 고립 수준

NOTE
트랜잭션 끼리 일관성 있는 데이터를 얼마나 허용할 것인지 정해놓은 수준이다!
각 격리레벨에 따른 이상현상 발생여부 (보통 2~3번째를 채택함)
고립 수준이 높을 수록 일관성은 보장되지만 그만큼 동시성이 떨어져 성능이 하락한다.

이상현상의 종류

NOTE

Dirty Read

T1이 T2가 롤백되기전 데이터를 읽음 (무효가 된 데이터)
트랜잭션 1이 쓰기 작업을 하는 트랜잭션 2가 작업한 중간 데이터를 읽음
어떤 트랜잭션이 아직 실행이 끝나지 않은 트랜잭션에 의한 변경사항을 보게되는 경우

Non Repeatable Read

트랜잭션 1이 읽기 값이 트랜잭션 2의 연산에 따라 달라짐
트랜잭션 1이 데이터를 읽고, 트랜잭션 2가 데이터를 수정한 뒤 트랜잭션 1이 다시 한번 읽은경우
트랜잭션 1이 다시 값을 읽으려고 하면 바로 전에 읽은 값이 달라지는 상황. (반복 불가능 읽기)

Phantom Read

트랜잭션 1의 읽기 값이 트랜잭션 2의 추가에 영향을 받음
트랜잭션 1이 데이터를 읽고, 트랜잭션 2가 데이터를 쓰고, 트랜잭션 1이 다시 한번 데이터를 읽음
트랜잭션 1이 읽기 작업을 반복한 경우 이전에 없던 데이터(유령 데이터)가 생기는 경우

트랜잭션 고립 수준의 종류

NOTE
DBMS는 트랜잭션을 동시에 실행시키면서 락보다 좀 더 완화된 방법으로 문제를 해결하기 위해 제공하는 명령어!
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ; SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SQL
복사
실제 적용사례

READ UNCOMMITED

공유/베타락이 걸려도 읽어버림
Dirty read가 발생
각 트랜잭션의 변경 내용이 COMMIT나 ROLLBACK 여부에 상관없이 값을 읽을 수 있게된다.

READ COMMITED

SELECT → 공유락 UPDATE → 베타락 다른 트랜잭션이 설정한 공유락은 읽고, 베타락은 읽지 못함
업데이트의 경우는 UnDo를 봐서 멀쩡하지만 삽입의 경우 2개만 보이는데 결과값이 3이나옴
SQL Server가 기본으로 사용하는 Isoliation Level이다.
트랜잭션 수행이 완료되고 COMMIT 된 데이터만 다른 트랜잭션에서 READ 하도록 허용하는 수준이다.

REPETABLE READ

자신의 데이터에 설정된 공유/베타 락을 트랜잭션 종료될떄까지 유지하여 업데이트할 수 없도록한다.
이론상 특정 트랜잭션에서 읽고 있는 데이터는 다른 트랜잭션에서 수정/삭제가 불가능하다. (삽입은 된다)
실제로 동작하는 방식은 자신의 트랜잭션 번호(ID)가 낮은 트랜잭션 번호에서 변경된 (Commit 된) 것만 읽게 되고, 자신의 트랜잭션 번호보다 높은 트랜잭션에서 변경된 것은 UNDO 영역에 백업된 레코드를 읽는다.

SERIALIZABLE

가장 단순하고 엄격한 격리 수준이다.
특정 트랜잭션에서 읽고 있는 데이터는 수정/삭제/삽입이 불가능하다.
모든 동작이 직렬화하게 동작한다.

DB 락(Lock)

NOTE
Lock ⇒ 트랜잭션의 원자성을 지키기위해 나온 개념!
session1이 트랜잭션을 시작하고 데이터를 수정하는 동안 아직 commit을 수행하지 않고 session2에서 동시에 같은 데이터를 수정하게 되면 트랜잭션의 원자성이 깨진다
1.
session1이 트랜잭션을 시작하고 lock을 얻어서 수정하려한다 (1~3)
2.
session2가 트랜잭션을 시작하려한다, 그런데 session1이 lock을 들고있어 대기함 (4~5)
3.
session1commit을 수행하면 lock을 반납하고, session2의 작업이 시작된다(6~7)
4.
session2commit을 수행하고 lock을 반납한다
[ 참고]
위의 그림과 같은 경우 session2가 무한정 대기하는게 아니라 일정시간을 넘어서면 대기시간 초과로 락 타임아웃 오류가 발생한다!
락 대기 시간은 설정할 수 있다
SET LOCK_TIMEOUT 60000; // 락 대기 시간 60초
SQL
복사

DB 락 - 조회

NOTE
보통 데이터를 조회할 때는 락을 획득하지 않고, 바로 데이터를 조회할 수 있다
하지만 데이터를 조회할 때도 락을 획득하는 경우가 있다 ⇒ select for update 구문을 사용한다!
select * from member where member_id 'memberA' for update
SQL
복사
[ 참고]
조회 시점에 락이 필요한 경우?
트랜잭션 종료 시점까지 해당 데이터를 다른 곳에서 변경하지 못하도록 강제로 막아야 할 떄 사용한다.
ex) memberA의 금액을 조회한 다음 이걸로 어떠한 계산을 수행해야해서 변경되면 안되는 경우