TIL

23/12/02 TIL __ 트랜잭션 3. 격리 수준과 프리즈마에서의 사용.

GABOJOK 2023. 12. 2. 23:47

 

오늘은 트랜젝션의 격리 수준 및 

프리즈마에서 사용법을 알아보겠다. 

 

🏞️  트랜잭션의 격리 수준  _ Isolation Level

  • 여러 트랜젝션이 동시에 처리될 때 다른 트랜젝션에서 변경 및 조회하는 데이터를 읽을 수 있도록 허용/거부 를 결정하기 위해 사용.
  • 데이터의 일관성과 동시성 처리 성능 사이에 균형을 잡는것.
  1. READ UNCOMMITTED
    • 커밋되지 않은 읽기를 허용함.
    • 다른 트랜잭션에 의해 작업중인 데이터를 읽게 되는 것을 말한다.. 
    • 가장 낮은수준의 격리.
    • 락을 걸지 않아 동시성은 높으나
    • 데이터 일관성이 쉽게 깨질수 있음.
    • 의도치 않은 데이터를 참조하게 되어 데이터의 일관성이 깨지게 되는 상황이 발생하게 된다.
  2. READ COMMITED
    • 커밋된 읽기만 허용
    • select문 실행시 공유락 건다.
    • 다른 트랜젝션이 데이터를 수정하고 있는 중에, 데이터를 읽을 수 없어 커밋되지 않은 읽기 현상이 발생하지 않는다.
  3. REPEATABLE READ
    • 읽기를 마쳐도 공유락 안품.
    • 트랜잭션 종료시까지 락을 유지
    • 공유락이 걸린 상태에서 데이터 수정 불가 그러나 삽입은 가능
    • 팬텀 읽기 발생할 수도 있다는 문제 발생.
    • 팬텀읽기란 
    • 트랜잭션을 수행하던 중 다른 트랜잭션에 의해 삭제된 데이터를 팬텀행(Phantom Rows)이라고 한다.
    • 여기서, 팬텀행에 해당하는 데이터를 읽는 것을 팬텀 읽기(Phantom Read)라고 함.
  4. SERIALIZABLE
    • 데이터를 읽는 동안 다른 트랜잭션이 해당 데이터를 읽거나 삽입할 수 없다ㅏ.
    • 새로운 데이터를 추가하는것 또한 불가능
    • 가장 높은 수준의 격리 수준.
    • 동시성이 떨어지는 문제점 존재.

 

 

 


 

🔮  Prisma Transaction

 

          1. Sequential 트랜젝션

          2. Interactive 트랜젝션

 

이렇게 나눠서 살펴보자. 

 

 

 

1. Sequential 트랜젝션 

  • 배열 형태이며, 순차적 실행된다.
  • 여러개의 쿼리를 하나의  트랜젝션으로 수행할 수 있는 Sequential 트랜젝션

 

import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

// Sequential 트랜잭션은 순차적으로 실행됩니다.
// 결과값은 각 쿼리의 순서대로 배열에 담겨 반환됩니다.
const [posts, comments] = await prisma.$transaction([
  prisma.posts.findMany(),
  prisma.comments.findMany(),
]);

 

 

 

혹은 로우쿼리로도 사용이 가능하다.

import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

// Sequential 트랜잭션은 순차적으로 실행됩니다.
// Raw Quyery를 이용하여, 트랜잭션을 실행할 수 있습니다.
const [users, userInfos] = await prisma.$transaction([
  prisma.$queryRaw`SELECT * FROM Users`,
  prisma.$queryRaw`SELECT * FROM UserInfos`,
]);

 

 

 

2. Interactive 트랜젝션

  • 자체적으로 트랜잭션의 성공과 실패를 관리하는 interactive 트랜잭션
  • 여기서 tx 라는 인자가 있는데, prisma 인스턴스 처럼 사용.   같은 기능임. 
  • 모든 비지니스 로직이 성공적으로 완료되거나 에러가 발생한 경우 Prisma 자체적으로 COMMIT 또는 ROLLBACK 을 실행.
  • 에러 발생시 자동 롤백 기능이 있음. 완전 굿
  • 트랜잭션을 관리하는 장점을 가지고 있다.
  • 또한 트랜잭션 진행중에도 비지니스 로직 처리 가능. 복잡한 쿼리 시나리오 효과적 구현.

 

import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

// Prisma의 Interactive 트랜잭션을 실행합니다.
const result = await prisma.$transaction(async (tx) => {
  // 트랜잭션 내에서 사용자를 생성합니다.
  const user = await tx.users.create({
    data: {
      email: 'testuser@gmail.com',
      password: 'aaaa4321',
    },
  });

  // 에러가 발생하여, 트랜잭션 내에서 실행된 모든 쿼리가 롤백됩니다.
  throw new Error('트랜잭션 실패!');
  return user;
});