CS/데이터베이스

[데이터베이스] 병행제어실습

rngPwns 2025. 6. 15. 16:09

트랜잭션

✅ 트랜잭션 실습 공식 구조


[1] 트랜잭션 시작

BEGIN TRANSACTION;

[2] 작업 수행 (INSERT / UPDATE / DELETE 등)

 

🔹 INSERT – 새 행 추가

설명:
새로운 데이터를 테이블에 추가하는 명령.
트랜잭션이 롤백되면 이 INSERT도 취소됨.

예시:
INSERT INTO Book VALUES(99, '데이터베이스', '한빛', 25000);


🔹 UPDATE – 기존 데이터 수정

설명:
조건에 맞는 행의 컬럼 값을 바꿈.
트랜잭션이 롤백되면 이전 값으로 되돌아감.

예시:
UPDATE Book SET bookname = '데이터베이스 개론' WHERE bookid = 99;


🔹 DELETE – 행 삭제

설명:
조건에 맞는 데이터를 테이블에서 제거함.
단, 트랜잭션 밖에서 수행되면 롤백 안 됨!

예시:
DELETE FROM Book WHERE bookid = 99;


🔸 그 외 참고용 – SELECT (읽기 전용)

설명:
데이터를 조회하는 것이므로 트랜잭션과 직접 관련은 없지만,
현재 트랜잭션에서의 변경 상태를 확인하는 데 사용함.

결과 나오게 함.

예시:
SELECT bookname FROM Book WHERE bookid = 99;


[3] (선택적으로) 저장점 지정

 
SAVE TRANSACTION 저장점이름;

👉 저장점은 중간 지점으로 롤백 가능하게 만들기 위한 체크포인트 역할을 함.


[4] (선택적으로) 저장점까지 롤백

* 롤백은 지금까지 했던 데이터 변경 작업을 전부 취소하고, 처음 상태로 되돌리는 명령

 
ROLLBACK TRANSACTION 저장점이름;

👉 저장점이 있으면 해당 지점까지 부분 롤백, 없으면 전체 롤백.


[5] (마지막에) 트랜잭션 확정 or 전체 취소

 
COMMIT; -- 지금까지 작업을 확정 저장 ROLLBACK TRANSACTION; -- 전체 롤백 (저장점 없을 때 사용)

✅ 추가 팁

상황                                                                명령어

               

트랜잭션 시작 BEGIN TRANSACTION;
중간저장 SAVE TRANSACTION a;
저장점으로 롤백 ROLLBACK TRANSACTION a;
전체 롤백 ROLLBACK TRANSACTION;
최종 확정 COMMIT;
 

⚠️ 주의할 점

  • DELETE를 트랜잭션 밖에서 하면 ROLLBACK 안 됨!
  • COMMIT TRANSACTION; 전에 ROLLBACK이 실행됐고 새로운 트랜잭션이 없다면 → 오류 발생

 

 

BEGIN TRANSACTION;

 

INSERT INTO Book VALUES(99, '데이터베이스', '한빛', 25000);

SELECT bookname FROM Book WHERE bookid=99;

SAVE TRANSACTION a;

UPDATE Book SET bookname = '데이터베이스 개론' WHERE bookid = 99;

SELELCT bookname FROM Book WHERE bookid = 99;

SAVE TRANSACTION b;

 

UPDATE Book SET bookname = '데이터베이스개론 및 실습' WHERE bookid = 99;

SELECT bookname FROM Book WHERE bookid =99;

ROLLBACK TRANSACTION b;

SELECT bookname FROM Book WHERE bookid = 99;

ROLLBACK TRANSACTION a;

SELECT bookname FROM Book WHERE bookid = 99;

COMMIT;

 

BEGIN TRANSACTION 

UPDATE Book SET bookname = '데이터베이스 개론 및 실습 2' WHERE bookid=99;

SELECT bookname FROM Book WHERE bookid = 99;

 

 

ROLLBACK TRANSACTION;

SELECT book

DELETE FROM Book WHERE bookid = 99;

COMMIT TRANSACTION; --> 이미 ROLLBACK 돼서 TRANSACTION이 아님 -> 오류

 

A1. ROLLBACK 이후에 트랜잭션은 이미 끝남

  • ROLLBACK TRANSACTION; 실행하면 → 현재 트랜잭션이 종료됨
  • 이후에 아무 작업을 해도 → 트랜잭션 안에서 일어나는 게 아님

A2. DELETE는 "트랜잭션 밖"에서 실행됨

  • 그래서 에러는 안 나지만, 롤백도 안 됨!
  • DELETE FROM Book ... 은 그냥 즉시 실행됨

 

병렬로 돌아감

 

1번째 상황

-- 1번째 실행

BEGIN TRNASACITON;

 

SELECT * FROM BOOK WHERE bookid=1;

 

UPDATE Book SET price=7100 WHERE bookid=1;

 

-- 2번째 실행 

BEGIN TRANSACTION;

 

SELECT * FROM Book WHERE bookid=1;

 

UPDATE Book SET price=price+100 WHERE bookid=1;

 

*1번 트랜잭션 COMMIT 이 안 돼서 대기중-> 3번째 실행에서 COMMIT 된 후 2번째 트랜잭션 수정결과 반영

 

--3번째 실행

SELECT * FROM Book WHERE bookid=1;

자기 변경사항 확인

COMMIT ;

 

--4번째 실행

SELECT * FROM Book WHERE bookid=1;

COMMIT;

 

 

 

  시점   트랜잭션                                   쿼리                                                          결과 

⏰1 1번 SELECT bookid=1 7000
⏰2 1번 UPDATE price = 7100 (잠금 상태, 다른 트랜잭션은 못 봄)
⏰3 2번 SELECT bookid=1 7000 (1번이 COMMIT 안 해서)
⏰4 2번 UPDATE price + 100 🚨 락 대기 상태
⏰5 1번 SELECT bookid=1 7100 (자기 변경 확인)
⏰6 1번 COMMIT → 락 해제됨
⏰7 2번 대기 해제 → UPDATE 실행 (price = 7200)  
⏰8 2번 SELECT bookid=1 7200
⏰9 2번 COMMIT 트랜잭션 2도 완료

 

2번째 상황

 

-- 1번째 실행

BEGIN TRAN

UPDATE Book SET price=price+100 WHERE bookid=1;

*트랜잭션 내부에는 저장 

 

-- 2번째 실행

BEGIN TRAN

UPDATE Book SET price=price*1.1 WHERE bookid=2;

(대기중)

-- 3번째 실행

UPDATE Book SET price=price+100 WHERE bookid=2;

*트랜잭션 내부에는 저장 

 

--4번째 실행

BEGIN TRAN

UPDATE Book SET price=price*1.1 WHERE bookid=1; 

(대기중)

>> 데드락 발생

 

 

오손읽기(dirty read)

🔹 READ UNCOMMITTED 이란?

  • 가장 낮은 트랜잭션 격리 수준
  • 다른 트랜잭션이 아직 COMMIT하지 않은 데이터도 볼 수 있음!
  • 이로 인해 발생하는 문제가 바로 👉 Dirty Read (더러운 읽기)

BEGIN TRAN  
SET TRANSACTION ISOLATION  
LEVEL READ UNCOMMITTED;

트랜잭션을 시작하면서, 격리 수준을 가장 낮은 수준으로 설정하는 명령

 

 

원래는 age = 30이 계속 나와야 하는데

READ UNCOMMITTED 격리 수준 때문에 COMMIT 안 된 값을 미리 읽게 돼서 age = 21처럼 바뀐다.

 

 

반복 불가능 읽기(non-repeatable read)

◼ 트랜잭션 1이 데이터를 읽고 트랜잭션 2가 데이터를 쓰고(갱신, UPDATE) 트랜잭션 1이 다시 한 번 데이터를 읽을 때 생기는 문제

◼ 트랜잭션 1이 읽기 작업을 다시 한 번 반복할 경우 이전의 결과와 다른 결과가 나오 는 현상

 

✅ 핵심 개념: READ COMMITTED = "확정된 것만 읽기"

  • 다른 트랜잭션이 COMMIT하지 않은 변경 내용은 절대 볼 수 없음
  • 그래서 Dirty Read(더러운 읽기)는 방지됨!
  • 단, 다른 트랜잭션이 COMMIT만 하면 그 뒤부터는 변경된 값이 바로 보여짐

 

 

유령 데이터 읽기(phantom read)

◼ 트랜잭션 1이 데이터를 읽고 트랜잭션 2가 데이터를 쓰고(삽입, INSERT) 트랜잭션 1 이 다시 한 번 데이터를 읽을 때 생기는 문제

◼ 트랜잭션 1이 읽기 작업을 다시 한 번 반복할 경우 이전에 없던 데이터(유령 데이터) 가 나타나는 현상

 

BEGIN TRAN  
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
ㄴ 트랜잭션 도중에 동일한 SELECT 결과가 항상 같도록 보장해주는 격리 수준

 

 

트랜잭션 고립 수준 명령어(transaction isolation level instruction)

▪ DBMS가 트랜잭션을 동시에 실행시키면서 락보다 좀 더 완화된 방법으로 문제를 해결하기 위해 제공하는 명령어

 

READ UNCOMMITTED (Level = 0)

✅ 트랜잭션 격리 수준(Isolation Level) 정리표

 레벨           격리 수준           Dirty Read        Non-repeatable Read     Phantom Read락        특성                 비고

     

0 READ UNCOMMITTED ✅ 가능 ✅ 가능 ✅ 가능 공유락 없음, 배타락만 필요 가장 낮은 수준 (NOLOCK 효과와 같음), COMMIT 안 된 데이터도 읽음
1 READ COMMITTED ❌ 방지 ✅ 가능 ✅ 가능 SELECT 시 공유락 설정, 끝나면 해제 SQL Server의 기본값. 확정된 데이터만 읽음
2 REPEATABLE READ ❌ 방지 ❌ 방지 ✅ 가능 SELECT 시 공유락 유지, 트랜잭션 끝날 때까지 유지 SELECT 결과 반복 보장, 갱신 차단
3 SERIALIZABLE ❌ 방지 ❌ 방지 ❌ 방지 범위 잠금(Range Lock) 설정, 완전 격리 동시성 최저, 완벽한 고립. SELECT도 미리 배타락
 

✅ 핵심 용어 간단 설명

  • Dirty Read: COMMIT 안 된 값을 읽음
  • Non-repeatable Read: 같은 SELECT인데 결과가 바뀜
  • Phantom Read: WHERE 조건에 새 행이 생겨 SELECT 결과에 추가됨
  • 공유락: 읽기 위한 잠금, 다른 트랜잭션의 쓰기 차단
  • 배타락: 쓰기 위한 잠금, 다른 트랜잭션의 읽기/쓰기 차단
배타락 (Exclusive Lock, X Lock) 데이터를 **수정(UPDATE/DELETE/INSERT)**할 때 거는 락. → 다른 트랜잭션이 읽지도, 쓰지도 못하게 막음
갱신손실 (Lost Update) 두 트랜잭션이 동시에 수정해서, 한 쪽 수정이 덮어씌워지는 문제

✅ 암기 요령

수준            외우기

 

0 아무 락도 안 걸고 마구 읽는다! → Dirty Read 허용
1 COMMIT된 것만 읽자 → Dirty Read는 막지만 반복성 없음
2 SELECT 결과는 그대로! → 반복 읽기 보장, 하지만 삽입은 막지 못함
3 완벽 격리! → 모든 트랜잭션을 순차처럼 처리 = 동시성 최저
 

✅ 선택 기준 팁

  • 속도 & 동시성 중시 → READ COMMITTED (기본값, 실무 추천)
  • 정확한 SELECT 반복 필요 → REPEATABLE READ
  • 완벽히 고립된 환경 필요 → SERIALIZABLE
  • 테스트 상황 또는 특수한 읽기 목적 → READ UNCOMMITTED

 

1. 반복불가능 읽기

 

 

2. 유령데이터 읽기 문제