트랜잭션(transaction)은 모두 반영되거나 하나도 반영되지 않아야 하는 작업 묶음입니다. 트랜잭션이 지켜야 할 네 특성을 머리글자로 모아 ACID라 부릅니다.
학생 102번이 운영체제(OS)를 빼고 네트워크(NW)를 듣기로 했습니다. 수강 표에서 OS 행을 지우고 NW 행을 넣어야 합니다. 두 문장입니다. 앞 문장만 반영되면 102번이 듣는 과목이 한 과목으로 줄어듭니다. 뒤 문장만 반영되면 세 과목이 됩니다. 둘 다 학사 기록이 틀어진 모습입니다. 그래서 두 문장을 한 묶음으로 묶고, 묶음 단위로 확정하거나 되돌립니다. 확정하는 문장이 COMMIT, 되돌리는 문장이 ROLLBACK입니다. 아래 그림은 이 두 문장이 한 묶음으로 확정되는 길과 막혀서 되돌아가는 길을 견줍니다.
1ACID 네 특성
| 특성 | 지켜 주는 것 | 깨지면 |
|---|---|---|
| 원자성(atomicity) | 트랜잭션의 문장이 모두 반영되거나 하나도 반영되지 않습니다 | 반쯤 반영된 데이터가 남습니다 |
| 일관성(consistency) | 트랜잭션 앞뒤로 데이터베이스가 정해 둔 규칙을 지킵니다 | 제약 조건을 어긴 데이터가 남습니다 |
| 독립성(isolation) | 끝나지 않은 트랜잭션이 바꾼 값은 다른 트랜잭션에 보이지 않습니다 | 다른 트랜잭션이 중간 값을 읽습니다 |
| 영속성(durability) | 확정한 변경은 장애가 나도 사라지지 않습니다 | 끝난 작업이 장애 뒤에 없어집니다 |
네 이름의 영문 머리글자(Atomicity·Consistency·Isolation·Durability)를 모아 ACID라 부릅니다. 독립성(isolation)은 자료에 따라 격리성이나 고립성이라고도 부릅니다. 영속성(durability)은 자료에 따라 지속성이라고도 부릅니다. 시험에서는 어느 이름으로도 나올 수 있습니다.
원자성과 일관성은 헷갈립니다. 묶음이 쪼개지지 않는 것이 원자성이고, 끝난 자리가 규칙을 지키는 것이 일관성입니다. 그림은 장면마다 네 특성을 하나씩 보입니다. 다음 절에서 장면을 따라가며 짚습니다.
2COMMIT과 ROLLBACK — 확정하는 길과 되돌아가는 길
그림의 문장은 한 세션에서 차례로 실행한 것입니다. 출발 장면의 수강 표에는 102번의 두 행(DS 70·OS 60)이 있습니다. 102번이 듣는 과목은 두 과목입니다.
DELETE로 OS 행을 지웁니다. 첫 문장이 실행되면 트랜잭션이 시작됩니다. Oracle은 트랜잭션을 여는 문장을 따로 쓰지 않습니다. 지운 것은 아직 임시입니다.
이어서 INSERT로 NW 행을 넣습니다. 이것도 아직 임시입니다. 같은 때 수강 표를 읽는 다른 트랜잭션에는 바뀐 값이 보이지 않고, 출발 값(DS 70·OS 60)이 그대로 보입니다. 독립성이 지켜지는 장면입니다.
COMMIT이 두 문장의 변경을 한꺼번에 확정합니다. 이제 다른 트랜잭션도 DS 70·NW 80을 봅니다. 확정한 변경은 장애가 나도 사라지지 않습니다. 영속성입니다.
여기까지가 끝까지 해낸 길입니다. 그림은 INSERT 자리에서 갈라져 막혀서 되돌아간 길도 보입니다.
넣으려는 과목코드가 과목 표에 없는 값이면 외래키 제약 조건에 막힙니다. 규칙을 어긴 데이터가 남지 않게 막은 것이 일관성입니다. 트랜잭션은 더 진행할 수 없어 실패 상태가 됩니다. 앞에서 지운 OS 행은 아직 임시로 남아 있습니다.
ROLLBACK이 트랜잭션이 바꾼 것을 모두 되돌립니다. OS 행이 돌아와 수강 표가 출발 장면과 똑같아집니다. 반쯤 반영된 표는 어느 장면에도 남지 않습니다. 원자성입니다.
3트랜잭션의 다섯 상태
그림의 점은 장면마다 상태 전이도 위를 옮겨 갑니다. 첫 문장에서 활동이 되고, 마지막 문장까지 끝내면 부분 완료, COMMIT을 마치면 완료가 됩니다. 막힌 길은 실패를 거쳐 철회로 끝납니다. 부분 완료에서도 확정을 쓰다 장애가 나면 실패로 갑니다. 문장은 다 끝났지만 아직 확정 전인 자리가 부분 완료입니다.
| 상태 | 언제 |
|---|---|
| 활동(active) | 첫 문장이 실행되어 트랜잭션이 도는 중입니다 |
| 부분 완료(partially committed) | 마지막 문장까지 끝났지만 아직 확정하지 않았습니다 |
| 완료(committed) | COMMIT이 끝나 변경이 확정되었습니다 |
| 실패(failed) | 더 진행할 수 없어 멈췄습니다 |
| 철회(aborted) | 바꾼 것을 모두 되돌려 시작 전으로 돌아갔습니다 |
예제
블록 하나가 한 세션이고, 저마다 처음 데이터에서 시작합니다. 마지막 SELECT로 102번이 듣는 과목을 봅니다.
COMMIT — 두 문장을 함께 확정한다
그림에서 COMMIT으로 끝까지 해낸 길입니다.
DELETE FROM 수강
WHERE 학번 = 102
AND 과목코드 = 'OS';
INSERT INTO 수강
VALUES (102, 'NW', 80);
COMMIT;
SELECT 과목코드,
점수
FROM 수강
WHERE 학번 = 102
ORDER BY 과목코드;
| 과목코드 | 점수 |
|---|---|
| DS | 70 |
| NW | 80 |
OS가 빠지고 NW가 들어와 102번은 여전히 두 과목을 듣습니다. COMMIT한 뒤에 ROLLBACK을 해도 되돌릴 것이 없습니다. 완료 상태에서는 되돌릴 수 없습니다.
막히면 되돌린다 — ROLLBACK
그림에서 막혀서 되돌아간 길입니다. 과목 표에 없는 과목코드 AI를 넣으려 합니다.
DELETE FROM 수강
WHERE 학번 = 102
AND 과목코드 = 'OS';
INSERT INTO 수강
VALUES (102, 'AI', 80);
ROLLBACK;
SELECT 과목코드,
점수
FROM 수강
WHERE 학번 = 102
ORDER BY 과목코드;
| 과목코드 | 점수 |
|---|---|
| DS | 70 |
| OS | 60 |
둘째 문장은 외래키 제약 조건에 막혀 다음 오류를 냅니다. 오류 속 SQLD는 이 예제를 돌린 데이터베이스 계정 이름입니다.
ORA-02291: integrity
constraint
(SQLD.수강_과목_FK) violated
- parent key not found
- 오류가 난 문장은 반영되지 않지만, 앞의 DELETE는 임시로 남아 있습니다. 이때 트랜잭션은 실패 상태입니다.
- ROLLBACK이 DELETE까지 되돌려 표가 출발과 같아집니다. 트랜잭션은 철회 상태로 끝납니다.
- 오류가 났다고 DBMS가 저절로 되돌리지는 않습니다. ROLLBACK을 실행해야 철회됩니다.
일부만 되돌리면 — SAVEPOINT
SAVEPOINT는 트랜잭션 중간에 이름을 붙여 둔 지점입니다.
ROLLBACK TO 지점은 그 지점 뒤의 변경만 되돌리고 트랜잭션을 끝내지 않습니다.
DELETE FROM 수강
WHERE 학번 = 102
AND 과목코드 = 'OS';
SAVEPOINT SP1;
INSERT INTO 수강
VALUES (102, 'NW', 80);
ROLLBACK TO SP1;
COMMIT;
SELECT 과목코드,
점수
FROM 수강
WHERE 학번 = 102
ORDER BY 과목코드;
| 과목코드 | 점수 |
|---|---|
| DS | 70 |
INSERT만 되돌려지고 DELETE는 남아 COMMIT으로 확정됐습니다. 102번은 한 과목만 듣게 됐습니다. 묶음을 중간에서 잘라 확정하면 이렇게 반쯤 반영된 결과가 남습니다. SAVEPOINT는 되돌릴 범위를 좁히는 도구이고, 원자성을 지켜 주는 것은 묶음 전체를 어디서 끊느냐입니다.
시험 포인트
- 필기: 트랜잭션은 모두 반영되거나 하나도 반영되지 않아야 하는 작업 묶음입니다. 네 특성은 원자성·일관성·독립성·영속성이고 머리글자를 모아 ACID라 부릅니다. 상태는 활동·부분 완료·완료·실패·철회 다섯입니다. 마지막 문장까지 끝났지만 확정 전이면 부분 완료, COMMIT을 마치면 완료입니다. COMMIT은 확정, ROLLBACK은 되돌리기이고, 완료한 트랜잭션은 ROLLBACK으로 되돌릴 수 없습니다.
- 실기: 원자성(Atomicity)·일관성(Consistency)·독립성(Isolation)·영속성(Durability), 묶어 ACID입니다. 독립성은 격리성·고립성, 영속성은 지속성으로도 씁니다. 상태는 활동(Active)·부분 완료(Partially Committed)·완료(Committed)·실패(Failed)·철회(Aborted)입니다.
확인 문제
1. 과목 표와 수강 표를 고치는 한 트랜잭션이 도중에 막혀 ROLLBACK됐습니다. 원자성이 지켜졌다면 끝난 뒤 데이터베이스는 어떤 모습일까요?
- ① 막히기 전에 실행한 문장의 변경만 남는다
- ② 트랜잭션이 시작하기 전과 똑같다
- ③ 막힌 문장을 건너뛰고 뒤 문장을 이어 실행해 끝까지 반영된다
- ④ 데이터베이스 전체가 가장 최근 COMMIT 시점으로 돌아간다
정답
②입니다. 원자성은 묶음을 쪼개지 않습니다. 끝까지 가지 못한 트랜잭션은 아무것도 반영하지 않은 것과 같아야 하므로, 되돌린 뒤 데이터베이스는 시작 전 모습입니다.
- ① 막히기 전 변경은 이미 반영됐으니 남는다고 봤습니다. 그 변경은 아직 임시이고, ROLLBACK이 함께 되돌립니다.
- ③ 원자성을 '어떻게든 끝까지 해낸다'로 봤습니다. 원자성은 끝까지 해내는 것을 보장하지 않고, 끝내지 못하면 전부 되돌립니다.
- ④ ROLLBACK이 데이터베이스 전체를 되돌린다고 봤습니다. 되돌아가는 것은 그 트랜잭션이 바꾼 것뿐이고, 같은 때 다른 트랜잭션이 확정한 변경은 그대로 남습니다.
2. 다음 (가)~(라)에 맞는 트랜잭션 특성의 이름을 한글 이름과 영문으로 함께 쓰세요. 답을 끝까지 쓴 뒤 정답을 펼치세요.
- (가) 과목 표에 새 과목을 넣는 문장과 그 과목을 다른 과목의 선수과목으로 지정하는 문장을 한 묶음으로 실행했습니다. 뒤 문장이 막히자 앞 문장이 넣은 행도 남지 않았습니다.
- (나) 수강 표에 행을 넣으려다 학생 표에 없는 학번을 가리켜 막혔습니다. 트랜잭션이 끝난 뒤에도 수강 표의 모든 행은 학생 표에 있는 학번만 가리킵니다.
- (다) 과목 OS의 학점을 고치는 트랜잭션이 아직 끝나지 않았습니다. 같은 때 과목별 학점을 모두 더하는 트랜잭션의 계산에는 고치기 전 학점이 들어갑니다.
- (라) 과목 NW의 학점을 고치고 작업을 마쳤다는 응답을 받았습니다. 그 직후 DBMS가 비정상 종료됐지만, 다시 올린 뒤에도 고친 학점이 남아 있습니다.
정답
받는 답: (가) 원자성(Atomicity) · (나) 일관성(Consistency) · (다) 독립성(Isolation) · (라) 영속성(Durability)
(가)의 실마리는 '뒤가 막히니 앞도 남지 않았다', (나)는 '끝난 뒤에도 규칙이 지켜진다', (다)는 '끝나지 않은 변경이 남의 계산에 들어가지 않는다', (라)는 '응답을 받은 뒤라면 장애 뒤에도 남는다'입니다.
- 같은 이름의 다른 꼴: (다) 격리성·고립성 · (라) 지속성 — 자료에 따라 이렇게도 부릅니다. 함께 받습니다. 영문은 Isolation·Durability 하나씩입니다.
- 틀리는 꼴 일관성 — (가)에: 끝난 자리가 규칙을 지키는 성질입니다. (가)는 규칙 이야기가 아니라 묶음이 쪼개지지 않았다는 이야기입니다.
- 틀리는 꼴 원자성 — (나)에: 묶음이 모두 반영되거나 하나도 반영되지 않는 성질입니다. (나)가 말하는 것은 끝난 뒤 외래키 규칙이 지켜졌다는 것입니다.
- 틀리는 꼴 영속성 — (다)에: 확정한 변경이 장애 뒤에도 남는 성질입니다. (다)에는 장애가 없습니다.
3. 학생 표를 고치는 트랜잭션이 아래 두 길로 끝났습니다. 각 길이 거치는 상태를 순서대로 이어 쓰세요. 꼴은 한글 이름을 화살표로 잇고 이름마다 영문을 괄호에 붙입니다. 답을 끝까지 쓴 뒤 정답을 펼치세요.
- (가) 문장을 모두 실행하고 COMMIT까지 마친 길입니다. 상태 셋을 지납니다.
- (나) 넣으려는 행의 학번이 이미 학생 표에 있어 막힌 뒤, 되돌려 끝난 길입니다. 상태 셋을 지납니다.
정답
받는 답: (가) 활동(Active) → 부분 완료(Partially Committed) → 완료(Committed) · (나) 활동(Active) → 실패(Failed) → 철회(Aborted)
두 길은 모두 첫 문장이 실행되는 활동에서 시작합니다. (가)는 마지막 문장을 끝낸 부분 완료를 거쳐 COMMIT으로 완료가 되고, (나)는 더 진행할 수 없는 실패를 거쳐 되돌아간 철회로 끝납니다.
- 같은 이름의 다른 꼴: 부분 완료를 Partial Commit으로 쓴 꼴 — 영문 표기가 다릅니다. Partially Committed로 씁니다.
- 틀리는 꼴 부분 완료 — (나)에: 마지막 문장까지 끝낸 상태입니다. (나)는 마지막 문장을 끝내지 못했습니다.
- 틀리는 꼴 완료 — (나)에: COMMIT이 끝난 상태입니다. (나)는 COMMIT에 이르지 못했습니다.
- 틀리는 꼴 철회 — (가)의 끝에: 바꾼 것을 되돌린 상태입니다. (가)는 되돌리지 않고 확정했습니다.
4. 다음 문장을 차례로 실행했습니다. 끝난 뒤 학과 표에 남는 학과코드를 고르세요.
INSERT INTO 학과
VALUES ('ME', '기계',
'공학관');
SAVEPOINT S1;
INSERT INTO 학과
VALUES ('CH', '화학',
'과학관');
ROLLBACK TO S1;
COMMIT;
SELECT 학과코드
FROM 학과
ORDER BY 학과코드;
- ① BA · CS · EE
- ② BA · CH · CS · EE
- ③ BA · CS · EE · ME
- ④ BA · CH · CS · EE · ME
정답
③입니다. ROLLBACK TO S1은 S1 뒤의 변경만 되돌립니다. S1 뒤의 INSERT(CH)는 되돌려지고, S1 앞의 INSERT(ME)는 남아 COMMIT으로 확정됩니다.
| 학과코드 |
|---|
| BA |
| CS |
| EE |
| ME |
- ①
ROLLBACK TO가 트랜잭션 전체를 되돌린다고 봤습니다. 저장점 뒤의 변경만 되돌아가고 트랜잭션은 이어집니다. - ② 되돌아가는 쪽을 거꾸로 봤습니다. 되돌아가는 것은 저장점 뒤에 한 일입니다.
- ④
ROLLBACK TO가 아무것도 되돌리지 않는다고 봤습니다. 되돌릴 범위를 좁힐 뿐이고, 범위 안의 변경은 사라집니다.
더 자세히: SQLD의 TCL · 모델이 표현하는 트랜잭션