트랜잭션이란?
-
데이터베이스 관리 시스템(DBMS)에서 하나의 논리적 작업 단위를 의미하며, 이 단위는 여러 데이터베이스 연산을 하나로 묶어 모두 성공하거나 모두 실패하도록 처리하는 작업
-
트랜잭션의 특징은 ACID 속성으로 정의된다.
ACID란?
- ACID란 원자성, 일관성, 격리성, 지속성을 나타내는 약어이다.
1. 원자성 (Atomicity)
- 원자성은 트랜잭션이 모두 성공하거나 모두 실패해야 한다는 것을 보장합니다.
- 즉, 트랜잭션 내의 여러 작업이 하나의 단위로 처리되며, 하나라도 실패하면 전체 트랜잭션이 롤백(rollback)되어, 데이터베이스는 트랜잭션 이전 상태로 복구됩니다.
2. 일관성 (Consistency)
- 일관성은 트랜잭션이 성공적으로 완료되면, 데이터베이스가 정상적인 상태를 유지해야 한다는 것을 의미합니다.
- 즉, 트랜잭션이 실행된 후에도 데이터베이스의 제약 조건(예: 고유성, 무결성 제약)이 깨지지 않도록 합니다.
3. 격리성 (Isolation)
- 격리성은 여러 트랜잭션이 동시에 실행될 때, 각 트랜잭션은 독립적으로 실행되어야 한다는 것을 의미합니다.
- 즉, 하나의 트랜잭션이 완료되기 전까지 다른 트랜잭션이 해당 작업의 중간 상태를 볼 수 없도록 합니다.
4. 지속성 (Durability)
- 지속성은 트랜잭션이 성공적으로 완료된 후, 그 결과가 영구적으로 저장되어 데이터베이스에 반영된다는 것을 보장합니다.
- 즉, 시스템에 장애가 발생하더라도 트랜잭션이 성공적으로 완료된 작업은 영구적으로 유지됩니다.
트랜잭션 사용 예시
try {
await prisma.$transaction([
prisma.gameResults.create({
data: {
user1Id: user1Id,
user2Id: user2Id,
user1Point: user1Point,
user2Point: user2Point,
},
}),
prisma.users.update({
where: { id: winnerId },
data: { rating: { increment: ratingChange } },
}),
prisma.users.update({
where: { id: loserId },
data: { rating: { decrement: ratingChange } },
}),
]);
} catch (error) {
throw new StatusError('경기 결과 저장 및 점수 업데이트 중 오류 발생', StatusCodes.BAD_GATEWAY);
}
- 위 코드는 경기 결과를 저장하고 승,패자의 rating을 증,감 시키는 코드입니다.
- 이 코드를 예시로 트랜잭션을 공부해봅시다.
위 코드는 세 가지 데이터베이스 작업을 처리합니다. 각각은 다음과 같습니다
1. gameResults 테이블에 경기 결과를 저장.
2. 승자의 rating을 증가
3. 패자의 rating을 감소
- 이 3가지 과정은 순차적으로 일어나기 때문에 앞에서 실패한다면 뒤에 코드 또한 실패해야합니다. 즉, 이 세 작업은 논리적으로 하나의 단위로 처리되어야 합니다.
트랜잭션을 사용하면 다음과 같은 이점이 있습니다.
-
원자성(Atomicity)
- 경기 결과를 저장한 뒤 승자 또는 패자의 rating을 업데이트하는 과정에서 오류가 발생한다면, 저장된 경기 결과도 롤백됩니다. 이로 인해 불완전한 상태의 데이터가 저장되는 것을 방지 할 수 있습니다.
-
일관성(Consistency)
- 세 작업이 하나의 트랜잭션으로 묶여 있으므로, 데이터의 상태가 일관되게 유지됩니다. 예를 들어, 경기 결과가 저장되었지만 승자나 패자의 rating이 업데이트되지 않는 상황을 피할 수 있습니다.
-
독립성(Isolation)
- 트랜잭션이 진행되는 동안 다른 트랜잭션이 이 작업에 영향을 미치지 않도록 보호됩니다. 다른 작업이 이 트랜잭션에 영향을 미치지 않으므로, 작업이 완료되기 전까지 다른 사용자가 승자나 패자의 rating을 조회하거나 수정하는 상황을 방지할 수 있습니다.
-
지속성(Durability)
- 트랜잭션이 성공적으로 완료되면, 그 결과는 영구적으로 데이터베이스에 반영됩니다.