트랜잭션
✅ 트랜잭션 실습 공식 구조
[1] 트랜잭션 시작
[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] (선택적으로) 저장점 지정
👉 저장점은 중간 지점으로 롤백 가능하게 만들기 위한 체크포인트 역할을 함.
[4] (선택적으로) 저장점까지 롤백
* 롤백은 지금까지 했던 데이터 변경 작업을 전부 취소하고, 처음 상태로 되돌리는 명령
👉 저장점이 있으면 해당 지점까지 부분 롤백, 없으면 전체 롤백.
[5] (마지막에) 트랜잭션 확정 or 전체 취소
✅ 추가 팁
트랜잭션 시작 | 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) 정리표
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. 유령데이터 읽기 문제
'CS > 데이터베이스' 카테고리의 다른 글
[데이터베이스] CH12. 데이터베이스 응용 기술 (0) | 2025.06.16 |
---|---|
[데이터베이스] 질의 최적화 (0) | 2025.06.16 |
[데이터베이스] ch11. 보안과 권한 관리 (0) | 2025.06.09 |
[데이터베이스] ch10. 회복과 병행 제어 (0) | 2025.06.09 |
[데이터베이스] ch09. 정규화 (0) | 2025.06.04 |