우리 코스에서는 트랜잭션을 세 번 다룰 거야. 그리고 매번 새로운 걸 발견하게 될 거야. 지금은 트랜잭션의 기본을 배워볼 거고, 코스 후반부에는 트랜잭션 격리 수준에 대해, 마지막에는 중첩 트랜잭션의 디테일을 파헤칠 거야.
트랜잭션이란?
일단 간단하게 정의부터 시작하자. 트랜잭션은 여러 동작을 묶어서 한 번에 실행하는 그룹이야. 끝.
여기서 중요한 결론이 나와: 만약 그룹 안의 어떤(진짜 아무거나!) 동작에서 에러가 나면, 나머지 동작들의 결과도 다 취소하고 시스템을 원래 상태로 돌려놔야 해.
SQL 관점에서 보면, 트랜잭션은 (예를 들어, 데이터 삽입, 수정, 삭제 같은) 여러 동작의 묶음이고, 트랜잭션 안의 모든 작업이 다 성공하거나, 아니면 아무것도 실행되지 않아야 해. 이 덕분에 데이터베이스 작업이 신뢰성 있고 일관성 있게 되는 거지. 특히 결제 처리나 연관 데이터 업데이트처럼 중요한 상황에서 말이야.
예를 들어, 네가 두 개의 은행 계좌 사이에서 돈을 이체한다고 해보자. 단순화해서 보면 두 개의 연속된 작업이 있어:
- 한 계좌에서 금액이 빠져나감.
- 다른 계좌에 같은 금액이 들어감.
만약 마지막 순간에 에러가 나거나(예를 들어, 서버가 다운됨), 아무도 손해보면 안 돼. 즉, 두 단계가 다 성공하면(트랜잭션이 커밋됨) OK, 아니면 둘 다 취소(트랜잭션이 롤백됨)해야 해.
트랜잭션과 ACID 원칙
트랜잭션은 ACID 원칙을 따르는데, 이건 네 가지 핵심 특성을 기억하게 해줘:
- Atomicity (원자성): 올-오어-낫싱. 트랜잭션 안의 모든 작업이 실행되거나, 아니면 다 취소돼.
- Consistency (일관성): 트랜잭션 전후로 데이터가 항상 올바른 상태로 남아있어야 해.
- Isolation (격리성): 각 트랜잭션은 마치 시스템에 자기 혼자만 있는 것처럼 동작해.
- Durability (지속성): 커밋된 데이터는 서버가 죽어도 남아있어.
트랜잭션을 다루는 기본 명령어
이제 실전 준비! 트랜잭션을 다루는 세 가지 핵심 명령어가 있어:
BEGIN
새로운 트랜잭션을 시작해. 이후의 모든 작업이 이 트랜잭션 안에서 실행돼.COMMIT
변경사항을 확정해. 이 명령어를 실행하면 모든 작업이 영구적으로 저장돼.ROLLBACK
변경사항을 취소해. 뭔가 잘못됐을 때 트랜잭션을 롤백하면 데이터가 원래대로 돌아가.
트랜잭션의 기본 문법
트랜잭션의 간단한 구조:
BEGIN;
-- 여기서 네 SQL 작업을 넣어
COMMIT;
ROLLBACK 사용 예시:
BEGIN;
-- students 테이블 변경
UPDATE students
SET grade = grade + 10
WHERE id = 1;
-- 오! 이게 실수였다는 걸 깨달았어.
ROLLBACK;
실제 문제에서 트랜잭션 사용 예시
예를 들어, 이런 테이블이 있다고 해보자:
students:
| id | name | grade |
|---|---|---|
| 1 | Otto Lin | 85 |
| 2 | Anna Song | 90 |
courses:
| course_id | course_name |
|---|---|
| 1 | 수학 |
| 2 | 역사 |
예를 들어, 학생을 코스에 등록시키고 동시에 평균 점수를 올리고 싶다고 해보자:
BEGIN;
-- 1단계: "코스 등록" 테이블에 레코드 추가
INSERT INTO course_enrollments (student_id, course_id)
VALUES (1, 2);
-- 2단계: 학생의 평균 점수 업데이트
UPDATE students
SET grade = grade + 5
WHERE id = 1;
COMMIT;
만약 첫 번째와 두 번째 단계 사이에 서버가 다운되면 어떻게 될까? 트랜잭션을 안 썼으면 데이터가 일관성 없는 상태가 됐을 거야: 코스 등록은 됐는데 점수는 안 올랐겠지. 하지만 트랜잭션을 쓰면 두 작업이 모두 성공하거나, 아니면 둘 다 취소돼.
트랜잭션 안에서 에러 처리하기
가끔 뭔가 잘못될 때가 있는데, 이럴 때 에러를 잘 처리해야 해. PostgreSQL에서는 에러가 나면 트랜잭션이 자동으로 롤백돼.
일부러 에러를 내보고 결과를 보자. 예를 들어, course_enrollments 테이블의 student_id 컬럼에 유니크 제약조건이 있다고 해보자. 중복된 행을 추가해보자:
BEGIN;
INSERT INTO course_enrollments (student_id, course_id)
VALUES (1, 2);
-- 트랜잭션 종료 (아직 실행 안 됨)
COMMIT;
이미 코스에 등록된 학생을 또 추가하려고 하면 에러가 나고, PostgreSQL이 자동으로 트랜잭션을 롤백해.
ROLLBACK으로 직접 롤백하기
에러를 미리 예측할 수 없을 때가 많으니까, 뭔가 잘못됐을 때 직접 트랜잭션을 롤백하고 싶을 거야:
BEGIN;
-- 새로운 학생 추가
INSERT INTO students (name, grade)
VALUES ('Omori Sanny', 75);
-- 오잉! 학생을 실수로 추가했다는 걸 깨달았어.
ROLLBACK;
ROLLBACK 명령어 이후에는 테이블이 그대로야 — Omori Sanny는 students에 추가되지 않아.
꿀팁 & 흔한 실수
트랜잭션을 쓸 때는 몇 가지 중요한 규칙만 기억하면 훨씬 쉬워져:
- 여러 단계가 필요한 작업(특히 여러 테이블을 수정할 때)은 항상 트랜잭션을 써.
- 변경사항 확정(
COMMIT)을 절대 잊지 마. 안 그러면 트랜잭션이 미완성 상태로 남고 데이터가 안 바뀌어. - 복잡한 작업은 트랜잭션으로 감싸서 데이터 일관성을 지켜.
- 어느 단계에서든 에러가 보이면
ROLLBACK쓰는 걸 두려워하지 마.
이제 트랜잭션으로 작업을 제어하는 방법을 알았으니, 직접 실습해보고 데이터 무결성을 지키는 트랜잭션을 더 깊이 배워보자!
GO TO FULL VERSION